Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.

This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 (CC BY-NC 3.0) United States License.

To cite this case study please use:

Wright, Carrie, and Ontiveros, Michael and Jager, Leah and Taub, Margaret and Hicks, Stephanie. (2020). https://github.com/opencasestudies/ocs-bp-co2-emissions. Mental Health of American Youth (Version v1.0.0).

Motivation


The following papers motivated this case study.

Twenge JM, Cooper AB, Joiner TE, Duffy ME, Binau SG. Age, period, and cohort trends in mood disorder indicators and suicide-related outcomes in a nationally representative dataset, 2005-2017. J Abnorm Psychol.128,3 (2019):185-199. doi:10.1037/abn0000410

Olfson, M., Blanco, C., Wang, S., Laje, G. & Correll, C. U. National Trends in the Mental Health Care of Children, Adolescents, and Adults by Office-Based Physicians. JAMA Psychiatry. 71, 81 (2014):81-90. doi: 10.1001/jamapsychiatry.2013.3074.

The main findings of the first article are:

Rates of major depressive episode in the last year increased 52% 2005–2017 (from 8.7% to 13.2%) among adolescents aged 12 to 17 and 63% 2009–2017 (from 8.1% to 13.2%) among young adults 18–25.

Serious psychological distress in the last month and suicide-related outcomes (suicidal ideation, plans, attempts, and deaths by suicide) in the last year also increased among young adults 18–25 from 2008–2017 (with a 71% increase in serious psychological distress), with less consistent and weaker increases among adults ages 26 and over.

Cultural trends contributing to an increase in mood disorders and suicidal thoughts and behaviors since the mid-2000s, including the rise of electronic communication and digital media and declines in sleep duration, may have had a larger impact on younger people, creating a cohort effect.

While the main findings of the second article are:

Compared with adult mental health care, the mental health care of young people has increased more rapidly.

Between 1995-1998 and 2007-2010, visits resulting in mental disorder diagnoses per 100 population increased significantly faster for youths (from 7.78 to 15.30 visits) than for adults (from 23.23 to 28.48 visits) (interaction: P < .001).

Psychiatrist visits also increased significantly faster for youths (from 2.86 to 5.71 visits).

While depression appear to be on the rise for youths, youths also appear to be seeking more mental health care.

In this case study we will evaluate data related to depression episodes and mental health care to evaluate trends overtime. We will be using data from the National Survey on Drug Use and Health (NSDUH). This data was also used in the first study.

Main Questions


Our main questions:

  1. How have depression rates in American youth changed since 2002, according to the NSDUH data?
  2. Do mental health services appear to be reaching more youths? How have rates differed between different youth subgroups (gender, ethnicity)?

Learning Objectives


avocado update these!

It may be a good idea to provide a link to Rstudio’s webpage. For the first few months using R, I did not differentiate between R and R Studio. It may be a good distinction to make at least implicitly by providing a link.

In this case study, we will determine the percent of youth in America that have had a major depressive episode in the past year since 2002. We will compare how different youth subgroups have changed over time (by age group (12-13,14-15, and 16-17), gender, ethnicity). We will especially focus on using packages and functions from the Tidyverse, such as rvest. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.


We will begin by loading the packages that we will need:

I made some modifications to the table below. The tidyverse package hyperlink referenced readr. I thought this was incorrect. I changed this to the tidyverse website and provided a different description. If this was indeed a typo, it may need to be fixed in other case studies.

Package Use
here to easily load and save data
tidyverse R packages for data science
rvest to scrape web pages

The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.

Context


According to other sources the rate of suicide has increased for most age groups in the United States over the past decade and a half.

source

While suicide does appear to be increasing amoung youths it also appears to be increasing amoung middle aged adults as well for both females and males.

source

According to the CDC:

Since 2008, suicide has ranked as the 10th leading cause of death for all ages in the United States. In 2016, suicide became the second leading cause of death among those aged 10–34 and the fourth leading cause among those aged 35–54.

#### [source]

So although sucide is on the rise for most age groups, sucide is one of the top two contributors to death for youths. Thus this warrents further examination of mental health of American youths.

[source]

If you are having thoughts of suicide, please know that you are not alone. If you are in danger of acting on suicidal thoughts, call 911. For support and resources, call the National Suicide Prevention Lifeline at 1-800-273-8255 or text 741-741 for the Crisis Text Line.

I took this from an article.https://www.theatlantic.com/health/archive/2020/06/why-suicide-rates-among-millennials-are-rising/612943/

If you or someone you know may be struggling with suicidal thoughts, you can call the U.S. National Suicide Prevention Lifeline at 800-273-TALK (8255) any time day or night, or chat online. I thook thos from this article. https://www.usatoday.com/story/news/nation/2020/01/30/u-s-suicide-rate-rose-again-2018-how-can-suicide-prevention-save-lives/4616479002/

covid:https://wellbeingtrust.org/areas-of-focus/policy-and-advocacy/reports/projected-deaths-of-despair-during-covid-19/

Historically, suicide rates were much higher before 1950, however, we are seeing an increase in the last 20 years.

[source]

Besides the US, other countries are also experiencing increased reates of depression in youths. See this report from the World Health Organization about rates of depression in other countries.

Great paper about what may be causing increased dpression - and the caveats of if we actually have increased depression: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3330161/

https://www.nimh.nih.gov/health/publications/teen-depression/index.shtml

According to the National Institute of Mental Health (NIMH):

If you are in crisis and need help, call this toll-free number for the National Suicide Prevention Lifeline (NSPL), available 24 hours a day, every day: 1-800-273-TALK (8255). The service is available to everyone. The deaf and hard of hearing can contact the Lifeline via TTY at 1-800-799-4889. All calls are confidential. You can also visit the Lifeline’s website at www.suicidepreventionlifeline.org.

The Crisis Text Line is another free, confidential resource available 24 hours a day, seven days a week. Text “HOME” to 741741 and a trained crisis counselor will respond to you with support and information over text message. Visit www.crisistextline.org.

Also see here for more information about how to recognise and help youths experiencing symptoms of depression.

Limitations


Perhaps “underestimates in the p-values…” is not the correct way to phrase this. I would look for a better way to word this.

Wording for this section should be reviewed.

There are some important considerations regarding this data analysis to keep in mind:

  1. We treat sample estimates—estimates of the true population value—as observed values. This produces understimates in the p-values of statistical tests conducted.

  2. Furthermore, the sampling mechanism utilized can introduce selection bias in cases where the the sampling methods do not produce a representative sample.

  3. Data is collected from human participants; this presents the potential for information bias, as there is the potential that partificipants in the sampling frame may for a variety of reasons report inaccurate information.

What are the data?


We will be using data from the National Survey on Drug Use and Health (NSDUH) which is directed by the Substance Abuse and Mental Health Services Administration (SAMHSA), an agency in the U.S. Department of Health and Human Services (DHHS).

This survey started in 1971 and is conducted annualy in all 50 states and the District of Columbia. Approximately 70,000 people (age 12 and up) are interviewed each year about health realted issues. Households are randomly selected and than a professional interviewer visists the addresses and asks one or two of the residents to inverview. The interviewer brings a laptop with them that the participants use to fill out the survey which typically takes an hour to complete. If a participant chooses to particpate they receive $30 in cash. All collected information is confidential and is used for disease surveillance and to guide public policy particuarlly focused on drug and alcohol use as well as mental health. See here for more details about the survey.

This data is made available publicly online on the Substance Abuse & Mental Health Data Archive.

At the website for the survey data, you can see that the results are displayed in many tables. Importantly, there is no obvious way to download the data directly from this particular website.

If one clicks on the TOC botton on the far right upper corner they will be directed to another website, where a large pdf document containing of all of the results can be downloaded.

We are interested in investigating how depression rates have changed and how youths are interacting with mental health services. Thus the following tables are of interest to us are:

Table Details
Table 11.1A Settings Where Mental Health Services Were Received in Past Year among Persons Aged 12 to 17: Numbers in Thousands, 2002-2018
Table 11.1B Settings Where Mental Health Services Were Received in Past Year among Persons Aged 12 to 17: Percentages, 2002-2018
Table 11.2A Major Depressive Episode in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Numbers in Thousands, 2004-2018
Table 11.2B Major Depressive Episode in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Percentages, 2004-2018
Table 11.3A Major Depressive Episode with Severe Impairment in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Numbers in Thousands, 2006-2018
Table 11.3B Major Depressive Episode with Severe Impairment in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Percentages, 2006-2018
Table 11.4A Receipt of Treatment for Depression in Past Year among Persons Aged 12 to 17 with Major Depressive Episode in Past Year, by Demographic Characteristics: Numbers in Thousands, 2004-2018
Table 11.4B Receipt of Treatment for Depression in Past Year among Persons Aged 12 to 17 with Major Depressive Episode in Past Year, by Demographic Characteristics: Percentages, 2004-2018

Data Import


Data is often made available online. Usually, the data we are interested in is made available for download on the page as a delimited text file or an excel file. However, sometimes data is not made available in this manner, such as the NSDUH survey data.

How do we proceed in this scenario?

We can manually copy each cell of data, however, this process is often inefficient, subject to error, and not reproducible. Say we wanted to run an analysis next year on the next years data and it happens to be formatted in the same way.

We can also use R for web scraping.

Web scraping is the process of extracting data from a website.

Basic steps of web scraping

There are two main steps to web scraping:

  1. Identify location of data on the webpage that will be scraped

  2. Save the webpage element to an object

We accomplish STEP 1 with our web browser.

We accomplish STEP 2 in the R programming environment.

I could not find the animation that I referred to on several occasions.

However, I was able to find the sources that I consulted to create the three step rvest process. They are included below

RStudio

Blog

In this case study we will scrape data from the tables on the NSDUH survey website. This data is available in a large PDF with all the results form the year. However it is not easy to find this PDF and it would be difficult and time consuming to find our tables of interest and to extract the data from the pdf with pdftools. Again, if we instead decided to copy paste the data from the website to another file that we would also need to import, this would not be as efficient or reproducible and might result in errors.

Alternatively, we will use the rvest package to scrape the data directly from the tables on the website. Assuming the data next year would be displayed in a similar manner, this could allow us simply modify our code based on the url for the data next year to run the same analysis on the data easily.

The rvest package can be thought of as the pdftools package for webscraping. Upon pulling the data, additional wrangling will likely be required; but like the pdftools package, rvest streamlines the extraction process.

Steps for scraping tables

The two web scraping steps for these tables can be broken down even further:

  1. Identify location of data that will be scraped
  • right-click to inspect element (webpage)
  • hover pointer over components of element (webpage) until the data has been found
  • copy Xpath of data sought
  1. Save webpage element to an object in R
  • import html code for the webpage
  • extract pieces of HTML documents (webpage) using Xpath
  • parse the extracted data into a data frame

Below is a animated overview of the process.


Now let’s go through each step together:

1) Identify location of data that will be scraped

First, let’s go to the web page with all the tables we are interested in scraping

Once on the webpage, there aren’t any visible options to download the data.

Right-click and select “Inspect”

A window opens.

This window allows us to glance at the internal mechanics of the webpage. To scrape the data from the webpage, we need to first learn a little bit about the components that make it the web page it is.

Hovering our mouse over the elements of the webpage highlights the respective section of the webpage it represents. By hovering over several elements—and clicking on the elements on the right side of the screen—we can indentify the element that contains the data we are looking for. Another option for identifying xpaths is to use the selectorgadget tool.

Right click on the element and copy the XPath. We will need this XPath for the next step.

Now we can return to the R programming environment.


2) Save webpage element to an object in R

For the first table we want to scrape, the XPath is /html/body/div[4]/div[1]/table. We use this Xpath with functions from the rvest package to scrape the data from this table.

Let’s explore this step in greater detail:

We need to:

  • import html code for the webpage
  • extract pieces (table) out of HTML documents (webpage) using Xpath
  • parse the html table into a data frame

To do this:

  • We import the html code using the read_html() function of the rvest package
  • We extract specific components of the webpage using the html_nodes() function of the rvest package
  • We convert this html table into a dataframe using the html_table()function of the rvest package

The rvest package provides wrappers for the xml2 and httr packages, thus we can just install and load the rvest package and it will install and load dependency packages like xml2 and httr and allow us to use functions from both of these packages.

In fact, when we load rvest the first time we see:

In this case, we are scraping table 11.1a from the website. First we assign the url to a character string to use within the read_html() function of the xml2 package.

One could also directly use the url but this is less convenient for piping.

Click here if you are unfamiliar with piping in R, which uses this %>% opperator

By piping we mean using the %>% pipe operator which are usable when loading the tidyverse or several of the packages within the tidyverse like dplyr becuase they load the magrittr package. This allows us to perform multiple sequential steps on one data input.

The read_html() function then allows us to save the html document for the webpage inside R.

{html_document}
<html lang="en">
[1] <head>\n<!-- Google Tag Manager --><script>(function(w,d,s,l,i){w[l]=w[l] ...
[2] <body>\r\n<!-- Google Tag Manager (noscript) -->\r\n<noscript><iframe src ...

Then we use the html_nodes() function of the rvest package to select just the table11.1a element of the webpage.

See this tutorial (and the answers in case you get stuck) on CSS selectors to understand more about how this function works to use the xpath to select the elements of interest from the webpage.

{xml_nodeset (1)}
[1] <table class="rti">\n<caption>Table 11.1A – Settings Where Mental Health  ...

Finally, the html_table() function of the rvest package parses the html object into a data frame.

[[1]]
     Setting Where Mental Health ServiceWas Received 2002 2003 2004 2005 2006
     2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
 [ reached 'max' / getOption("max.print") -- omitted 21 rows ]
List of 1
 $ :'data.frame':   21 obs. of  18 variables:
  ..$ Setting Where Mental Health ServiceWas Received: chr [1:21] "SPECIALTY MENTAL HEALTH SERVICE1" "Outpatient" "Private Therapist, Psychologist,\r\n   Psychiatrist, Social Worker, or\r\n   Counselor" "Mental Health Clinic or Center" ...
  ..$ 2002                                           : chr [1:21] "2,898a" "2,662a" "2,254a" "611a" ...
  ..$ 2003                                           : chr [1:21] "3,065a" "2,795a" "2,347a" "635a" ...
  ..$ 2004                                           : chr [1:21] "3,348a" "3,015a" "2,523a" "716a" ...
  ..$ 2005                                           : chr [1:21] "3,362a" "3,048a" "2,573a" "657a" ...
  ..$ 2006                                           : chr [1:21] "3,255a" "2,931a" "2,416a" "587a" ...
  ..$ 2007                                           : chr [1:21] "3,104a" "2,787a" "2,365a" "583a" ...
  ..$ 2008                                           : chr [1:21] "3,129a" "2,837a" "2,408a" "567a" ...
  ..$ 2009                                           : chr [1:21] "2,925a" "2,650a" "2,296a" "537a" ...
  ..$ 2010                                           : chr [1:21] "2,920a" "2,635a" "2,265a" "547a" ...
  ..$ 2011                                           : chr [1:21] "3,101a" "2,842a" "2,409a" "547a" ...
  ..$ 2012                                           : chr [1:21] "3,118a" "2,846a" "2,427a" "610a" ...
  ..$ 2013                                           : chr [1:21] "3,341a" "3,064a" "2,572a" "731a" ...
  ..$ 2014                                           : chr [1:21] "3,369a" "3,110a" "2,698a" "760a" ...
  ..$ 2015                                           : chr [1:21] "3,253a" "2,958a" "2,532a" "792a" ...
  ..$ 2016                                           : chr [1:21] "3,598a" "3,239a" "2,819a" "929" ...
  ..$ 2017                                           : chr [1:21] "3,646a" "3,328" "2,908" "995" ...
  ..$ 2018                                           : chr [1:21] "3,901" "3,547" "3,080" "977" ...

We can see that the output is a list with one element, to extract the data from the list we will use brackets [[]] to select the first element of the list.

Putting this all of this together we can do the entire porcess like this with our pipe opperator %>%.

Now need to repeat the above process for the other tables we are interested in.

Writing a function to scrape multiple tables

We can create a function to accomplish this succinctly. Functions allow us to perform the same process on multiple data inputs. See this other case study for more details about how to write a function.

In general, the process pf writing functions involves first specifying an input that is used within the function to create an output. In this case the data input is XPATH which will be replaced by an actual xpath and the nused in the subsequent steps to scrape the data from each table that an xpath is supplied for.

We will all this function scarper.

Now we can apply the function we created to each of the xpaths for each of the tables on the website that we would like to use in our data analysis.

Great! We have successfully scraped the data.

Now we need to wrangle the data.

Data Exploration and Wrangling


Now that we’ve imported the data, let’s see if we can wrangle a table. Since the data appears to be formated in a similar way in each of the tables, it is likely that whatever steps we take to wrangle this first table will also be necessary in the wrangling of subsequent tables. This is because well-maintained data sources often format different datasets similarly. We can take advantage of this similarity to speed up the wrangling process.

Table11.1a

First we want to remove the last row of our data frame, which happens to be the legend of our table. Recall from looking at the website that there is a legend for this table.

We can take a look at the last row using the tail function of the dplyr package. We can specify that we only want to see the last row by using the n = 1 argument.

# A tibble: 1 x 18
  `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
  <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
1 "* = low precis… "* = … "* = … "* = … "* = … "* = … "* = … "* = … "* = …
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

We can see that the legend is repeated for every column. Let’s take a look at the year 2004 column.

# A tibble: 1 x 1
  `2004`                                                                        
  <chr>                                                                         
1 "* = low precision; -- = not available; da = does not apply; nc = not compara…

Let’s save this so that we can refer back to it later:

Another way to look at the last row is to use the n() function of the dplyr package. This function can be used inside other dplyr functions and it counts the total number of observations of a group. Within the slice() function of the dplyr packge, it allows you to refer the full length of the object.

# A tibble: 1 x 18
  `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
  <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
1 "* = low precis… "* = … "* = … "* = … "* = … "* = … "* = … "* = … "* = …
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

We can use the slice() function of the dplyr package to remove this row, by using the slicefunction to select from the first row using 1: to the second to last row using n()-1.

We are also going to use a special pipe opperator from the magrittr package called the compound assignment pipe-operator or sometimes the double pipe operator. This allows us to use the table11.1a as our input and reasign it at the end after all the steps have been performed.

Now let’s take a look at data:

# A tibble: 20 x 18
   `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
   <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 "SPECIALTY MENT… "2,89… "3,06… "3,34… "3,36… "3,25… "3,10… "3,12… "2,92…
 2 "Outpatient"     "2,66… "2,79… "3,01… "3,04… "2,93… "2,78… "2,83… "2,65…
 3 "Private Therap… "2,25… "2,34… "2,52… "2,57… "2,41… "2,36… "2,40… "2,29…
 4 "Mental Health … "611a" "635a" "716a" "657a" "587a" "583a" "567a" "537a"
 5 "Partial Day Ho… "440"  "425"  "439"  "449"  "471"  "416"  "374a" "340a"
 6 "In-Home Therap… "693a" "656a" "762a" "731a" "719a" "707a" "716a" "657a"
 7 "Inpatient or R… "509a" "542a" "629"  "619"  "596"  "581a" "539a" "524a"
 8 "Hospital"       "422a" "467a" "515"  "529"  "516"  "511a" "469a" "440a"
 9 "Residential Tr… "224a" "233a" "299"  "229a" "225a" "199a" "198a" "213a"
10 "NONSPECIALTY M… "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "3,43…
11 "Education2,3"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "2,93…
12 "School Social … "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "2,28…
13 "Special School… "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "975a"
14 "General Medici… ""     ""     ""     ""     ""     ""     ""     ""    
15 "Pediatrician o… "657a" "732"  "840"  "810"  "694"  "692"  "710"  "605a"
16 "Juvenile Justi… ""     ""     ""     ""     ""     ""     ""     ""    
17 "Juvenile Deten… "--"   "--"   "--"   "--"   "--"   "--"   "--"   "109a"
18 "Child Welfare"  ""     ""     ""     ""     ""     ""     ""     ""    
19 "Foster Care or… "157a" "179a" "158a" "143a" "129"  "114"  "118"  "92"  
20 "SPECIALTY MENT… "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "1,22…
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

Great! We can see the the legend is no longer part of the data.

Now let’s use the legend to recode the data. There are many different values for missing data, that we would like to replace with NA instead. We can use the pull() function of the dplyr package to take a look at the legend data:

[1] "* = low precision; -- = not available; da = does not apply; nc = not comparable due to methodological changes; nr = not reported due to measurement issues.\r\nNOTE: Some 2006 to 2010 estimates may differ from previously published estimates due to updates (see Section 3.3.5 in Chapter 3 of the 2018 National Survey on Drug Use and Health: Methodological Summary and Definitions).\r\nNOTE: Mental health services for persons aged 12 to 17 includes treatment/counseling for emotional or behavioral problems not caused by drug or alcohol use. Respondents with unknown mental health service information were excluded.\r\nNOTE: Respondents could indicate multiple service settings; thus, the response categories are not mutually exclusive.a The difference between this estimate and the 2018 estimate is statistically significant at the .05 level. Rounding may make the estimates appear identical.1 Because of revisions in 2013 to Specialty Mental Health Service estimates, these 2002 to 2012 estimates may differ from estimates published prior to the 2013 NSDUH.2 Because of revisions in 2009 to the questions on the Source of Youth Mental Health Education Services, these estimates are not comparable with the education services estimates published prior to the 2009 NSDUH.3 Respondents who did not report their school enrollment status, who reported not being enrolled in school in the past 12 months, or who reported being home-schooled were not asked about receipt of mental health services from this setting; however, respondents who reported not being enrolled in school in the past 12 months were classified as not having received treatment/counseling from this setting.\r\nDefinitions: Measures and terms are defined in Appendix A.\r\nSource: SAMHSA, Center for Behavioral Health Statistics and Quality, National Survey on Drug Use and Health, 2002-2018."

Looks like we want to replace values that are: *, --, da, nc, and nr. We can use the na_if() function to recode these values to NA.

avocado… there isnt support for doing this in one command… but could at least do two commands

# A tibble: 20 x 18
   `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
   <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 "SPECIALTY MENT… 2,898a 3,065a 3,348a 3,362a 3,255a 3,104a 3,129a 2,925a
 2 "Outpatient"     2,662a 2,795a 3,015a 3,048a 2,931a 2,787a 2,837a 2,650a
 3 "Private Therap… 2,254a 2,347a 2,523a 2,573a 2,416a 2,365a 2,408a 2,296a
 4 "Mental Health … 611a   635a   716a   657a   587a   583a   567a   537a  
 5 "Partial Day Ho… 440    425    439    449    471    416    374a   340a  
 6 "In-Home Therap… 693a   656a   762a   731a   719a   707a   716a   657a  
 7 "Inpatient or R… 509a   542a   629    619    596    581a   539a   524a  
 8 "Hospital"       422a   467a   515    529    516    511a   469a   440a  
 9 "Residential Tr… 224a   233a   299    229a   225a   199a   198a   213a  
10 "NONSPECIALTY M… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3,430a
11 "Education2,3"   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,931a
12 "School Social … <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,286 
13 "Special School… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975a  
14 "General Medici… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
15 "Pediatrician o… 657a   732    840    810    694    692    710    605a  
16 "Juvenile Justi… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 "Juvenile Deten… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109a  
18 "Child Welfare"  <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
19 "Foster Care or… 157a   179a   158a   143a   129    114    118    92    
20 "SPECIALTY MENT… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1,226a
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

Now let’s rename the first column using the rename() function of the dplyr package. This requires listing the new name first like so: new_name = old_name.

# A tibble: 6 x 18
  MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
  <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
1 "SPECIALTY… 2,898a 3,065a 3,348a 3,362a 3,255a 3,104a 3,129a 2,925a 2,920a
2 "Outpatien… 2,662a 2,795a 3,015a 3,048a 2,931a 2,787a 2,837a 2,650a 2,635a
3 "Private T… 2,254a 2,347a 2,523a 2,573a 2,416a 2,365a 2,408a 2,296a 2,265a
4 "Mental He… 611a   635a   716a   657a   587a   583a   567a   537a   547a  
5 "Partial D… 440    425    439    449    471    416    374a   340a   362a  
6 "In-Home T… 693a   656a   762a   731a   719a   707a   716a   657a   674a  
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

Nice!

Now you may notice that the individual values have an "a" after the numeric value.

According to the legend this indicates if “the difference between this estimate and the 2018 estimate is significant at the .05 level.”

While this is useful information, it makes it difficult to work with our numeric values, so we want to remove them.

Since lower case “a” values occur in the first column values, we want to makes sure we dont remove these.

So how can we do this? We can use the stringr package to modify character strings. and we can use the dplyr functions mutate(), select() and across() to specify want columns we want to change.

Currently all of our data is of class character as indicated by the <chr> under the column names.

Click here for an explanation of what a character string is

There are several classes of data in R programming. Character is one of these classes. A chacter string is an individual data value made up of characters. This can be a paragraph, like the legend for the table, or it can be a single letter or number like the letter "a" or the number "3". If data is of class character, than the numeric values will not be processed like a numeric value in a mathematical sense. If you want your numeric values to be interpreted that way, they need to be converted to a numeric class. The options typically used are integer (which has no decimal place) and double precision (which has a decimal place).

The stringr package has functions that allow us to replace (the str_replace() function) or remove(the str_remove() function) characters.

To use these we need to be able to specify what we want to remove and replace.

Here is a part of a cheatsheet about string manipulation from rstudio.

We can see that we can refer to any digit (such as 1,2,3 etc.) as [:digit:]. We can also see that we can refer to any punction mark as [:punct:]. Finally, we see that spaces and tabls can be refered to as [:blank:].

If we take a closer look at the first column of our table (using the pull() function of the dplyr package), we can see that besides the "a" values that we see adjacent to our numeric values in the body of the table, we also some large white spaces, some numeric values, instances of \r\n, as well as some commas and other punctuation marks.

 [1] "SPECIALTY MENTAL HEALTH SERVICE1"                                                                                
 [2] "Outpatient"                                                                                                      
 [3] "Private Therapist, Psychologist,\r\n   Psychiatrist, Social Worker, or\r\n   Counselor"                          
 [4] "Mental Health Clinic or Center"                                                                                  
 [5] "Partial Day Hospital or Day Treatment\r\n   Program"                                                             
 [6] "In-Home Therapist, Counselor, or Family\r\n   Preservation Worker"                                               
 [7] "Inpatient or Residential1"                                                                                       
 [8] "Hospital"                                                                                                        
 [9] "Residential Treatment Center"                                                                                    
[10] "NONSPECIALTY MENTAL HEALTH\r\nSERVICE2"                                                                          
[11] "Education2,3"                                                                                                    
[12] "School Social Worker, School Psychologist,\r\n   or School Counselor"                                            
[13] "Special School or Program within a Regular\r\n   School for Students with Emotional or\r\n   Behavioral Problems"
[14] "General Medicine"                                                                                                
[15] "Pediatrician or Other Family Doctor"                                                                             
[16] "Juvenile Justice"                                                                                                
[17] "Juvenile Detention Center, Prison, or Jail"                                                                      
[18] "Child Welfare"                                                                                                   
[19] "Foster Care or Therapeutic Foster Care"                                                                          
[20] "SPECIALTY MENTAL HEALTH SERVICES\r\nAND EDUCATION, GENERAL MEDICINE\r\nOR CHILD WELFARE SERVICES1,2,3"           

We can use the str_remove_all() function which is a variant of the str_remove() function of the stringr package (which allows us to remove all occurences of sepcificed characters in each row rather than just the first occurance, which is what str_remove() does), to remove the digit values, the \r\n characters and the punctionation marks from the column called MHS_setting.

Using the mutate() function we specify that we want to change this particular column and replace it with a version of this column that has removed characters that match digits, r\n or punctionation marks.

We need to specify that the character strings that should be used can be found ing the MHS_setting column by using the string = argument and the patterns to find and remove are specified using the pattern = argument.

To allow us to look for all three of these patterns at the same time, we can use the | symbol between each pattern.

We also want to replace the spaces with an underscore. We can see that sometimes there appears to be more than one space. We can specify that we want any occurance of 1 or more to be replaced by using the {1,} notation.

See here for an explanation of this on the cheat sheet:

So now we will use the str_replace_all() function of the stringr package. In this case we also need to specify a replacement with the replacement = argument.

Now to finally remove the “a” values and the commas from the body of the table we can use str_remove_all() function yet again. However this time to specify that we want all columns except the first column called MHS_setting, we can use the across() function of the dplyr package. This allows us to specify what columns we want to mutate by using the .cols = argument. We can select all columns except the first column called MHS_setting by using a minus sign - in front of the column name.

# A tibble: 20 x 18
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 SPECIALTY_… 2898   3065   3348   3362   3255   3104   3129   2925   2920  
 2 Outpatient  2662   2795   3015   3048   2931   2787   2837   2650   2635  
 3 Private_Th… 2254   2347   2523   2573   2416   2365   2408   2296   2265  
 4 Mental_Hea… 611    635    716    657    587    583    567    537    547   
 5 Partial_Da… 440    425    439    449    471    416    374    340    362   
 6 InHome_The… 693    656    762    731    719    707    716    657    674   
 7 Inpatient_… 509    542    629    619    596    581    539    524    531   
 8 Hospital    422    467    515    529    516    511    469    440    447   
 9 Residentia… 224    233    299    229    225    199    198    213    217   
10 NONSPECIAL… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3430   3465  
11 Education   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2931   2957  
12 School_Soc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2286   2214  
13 Special_Sc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975    1054  
14 General_Me… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
15 Pediatrici… 657    732    840    810    694    692    710    605    601   
16 Juvenile_J… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 Juvenile_D… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109    80    
18 Child_Welf… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
19 Foster_Car… 157    179    158    143    129    114    118    92     108   
20 SPECIALTY_… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1226   1283  
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

Our table is looking much better!

We would also like to remove a couple of rows that are completely empty. These are the rows where the first column values are Genearl_Medicine and Juvenile_Justice. If we look at the website, we can see that these were leading line with no data.

We can remove them using the filter() function of the dplyr package. We can specify that we dont want to keep these rows by using the != not equal to opperator.

# A tibble: 18 x 18
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 SPECIALTY_… 2898   3065   3348   3362   3255   3104   3129   2925   2920  
 2 Outpatient  2662   2795   3015   3048   2931   2787   2837   2650   2635  
 3 Private_Th… 2254   2347   2523   2573   2416   2365   2408   2296   2265  
 4 Mental_Hea… 611    635    716    657    587    583    567    537    547   
 5 Partial_Da… 440    425    439    449    471    416    374    340    362   
 6 InHome_The… 693    656    762    731    719    707    716    657    674   
 7 Inpatient_… 509    542    629    619    596    581    539    524    531   
 8 Hospital    422    467    515    529    516    511    469    440    447   
 9 Residentia… 224    233    299    229    225    199    198    213    217   
10 NONSPECIAL… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3430   3465  
11 Education   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2931   2957  
12 School_Soc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2286   2214  
13 Special_Sc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975    1054  
14 Pediatrici… 657    732    840    810    694    692    710    605    601   
15 Juvenile_D… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109    80    
16 Child_Welf… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 Foster_Car… 157    179    158    143    129    114    118    92     108   
18 SPECIALTY_… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1226   1283  
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

Now we would like to change the shape of our table so that we have a new column that reperesents the year and a new column that represents the value for that year. To do so we will be making our table “longer”, meaning that it will have fewer rows and more columns. See here for more information about different table formats, typically refreed to as wide and long or sometimes narrow.

We will use the pivot_longer() function of the tidyr package to change the shape of our table.

There are 3 main arguments in this function:
1) cols - which specifies what columns to collapse
2) names_to - which specifies the name of the new column that will be created that will contain the column names of the columns you are collapsing
3) values_to - which specifies the name of the new column that will be created that will contain the values from the columns you are collapsing

To specify that we want to collapse all columns except the MHS_setting column we can again use the minus sign.

# A tibble: 306 x 3
   MHS_setting                     Year  Number
   <chr>                           <chr> <chr> 
 1 SPECIALTY_MENTAL_HEALTH_SERVICE 2002  2898  
 2 SPECIALTY_MENTAL_HEALTH_SERVICE 2003  3065  
 3 SPECIALTY_MENTAL_HEALTH_SERVICE 2004  3348  
 4 SPECIALTY_MENTAL_HEALTH_SERVICE 2005  3362  
 5 SPECIALTY_MENTAL_HEALTH_SERVICE 2006  3255  
 6 SPECIALTY_MENTAL_HEALTH_SERVICE 2007  3104  
 7 SPECIALTY_MENTAL_HEALTH_SERVICE 2008  3129  
 8 SPECIALTY_MENTAL_HEALTH_SERVICE 2009  2925  
 9 SPECIALTY_MENTAL_HEALTH_SERVICE 2010  2920  
10 SPECIALTY_MENTAL_HEALTH_SERVICE 2011  3101  
# … with 296 more rows

We can see that our table is now much longer- as we have 340 rows!

Question Opportunity

Why do we have 340 rows now?

Finally, we also want to change our values to be numeric as opposed to character so that we can use them in mathematical functions. We can use the base as.numeric() function. Again we will use the across() function to indicate what varaibles we wish to mutate.

# A tibble: 306 x 3
   MHS_setting                      Year Number
   <chr>                           <dbl>  <dbl>
 1 SPECIALTY_MENTAL_HEALTH_SERVICE  2002   2898
 2 SPECIALTY_MENTAL_HEALTH_SERVICE  2003   3065
 3 SPECIALTY_MENTAL_HEALTH_SERVICE  2004   3348
 4 SPECIALTY_MENTAL_HEALTH_SERVICE  2005   3362
 5 SPECIALTY_MENTAL_HEALTH_SERVICE  2006   3255
 6 SPECIALTY_MENTAL_HEALTH_SERVICE  2007   3104
 7 SPECIALTY_MENTAL_HEALTH_SERVICE  2008   3129
 8 SPECIALTY_MENTAL_HEALTH_SERVICE  2009   2925
 9 SPECIALTY_MENTAL_HEALTH_SERVICE  2010   2920
10 SPECIALTY_MENTAL_HEALTH_SERVICE  2011   3101
# … with 296 more rows

Now we see that the Year and Number variables are of class double because of the <dbl> under the column name.

Now we want to wrangle all of our other tables which are formatted similarly.

We can again write a function to simplify this process.

The function needs to:

  • remove the last row of the table
  • get rid of certain patterns
  • transition the data to long format

I included the following line to help separate the tables.


Table11.1a

We then apply this function to the table, ridding the table of headings and ensuring some of our commons are correctly of numeric class.

[1] 21 18

We write a function to simplify this process for data that uses demographic groups as units of observation.

The function needs to:

  • remove the last row of the table
  • get rid of certain patterns
  • transition the data to long format

I included the following line to help separate the tables.


Table11.2a

We use the produced function to wrangle the next pair of tables.

[1] 18 16
# A tibble: 5 x 2
  Demographic                  n
  <chr>                    <int>
1 AGE GROUP                   15
2 AIAN                         1
3 GENDER                      15
4 HISPANIC ORIGIN AND RACE    15
5 NHOPI                       14

I included the following line to help separate the tables.


Table11.2b

[1] 18 16
# A tibble: 5 x 2
  Demographic                  n
  <chr>                    <int>
1 AGE GROUP                   15
2 AIAN                         1
3 GENDER                      15
4 HISPANIC ORIGIN AND RACE    15
5 NHOPI                       14

We repeat this process for the remaining tables.

I included the following line to help separate the tables.


Table 11.3a

[1] 18 14
# A tibble: 5 x 2
  Demographic                  n
  <chr>                    <int>
1 AGE GROUP                   13
2 AIAN                         2
3 GENDER                      13
4 HISPANIC ORIGIN AND RACE    13
5 NHOPI                       13

I included the following line to help separate the tables.


Table 11.3b

[1] 18 14
# A tibble: 5 x 2
  Demographic                  n
  <chr>                    <int>
1 AGE GROUP                   13
2 AIAN                         2
3 GENDER                      13
4 HISPANIC ORIGIN AND RACE    13
5 NHOPI                       13

I included the following line to help separate the tables.


Table 11.4a

[1] 18 16
# A tibble: 7 x 2
  Demographic                  n
  <chr>                    <int>
1 AGE GROUP                   15
2 AIAN                        15
3 Asian                       15
4 GENDER                      15
5 HISPANIC ORIGIN AND RACE    15
6 NHOPI                       15
7 Two or More Races           12

I included the following line to help separate the tables.


Table 11.4b

[1] 18 16
# A tibble: 7 x 2
  Demographic                  n
  <chr>                    <int>
1 AGE GROUP                   15
2 AIAN                        15
3 Asian                       15
4 GENDER                      15
5 HISPANIC ORIGIN AND RACE    15
6 NHOPI                       15
7 Two or More Races           12

Now that we’ve wrangled the data, we can go ahead and proceed with our analysis.

Data Analysis


In this section, we only analyzed data from tables 2-4. Data from table 1 is very different than data from tables 2-4. For expediency, I did not include an example with data frome table 1. The following code, however, can easily be repurposed to accomplish that once a specific group has been identified to conduct the test on.

We would like to conduct a chi-squared test for independence.

To conduct this statistical test, we need to produce a 2x2 table.

The following code subsets the data we need and makes the necessary manipulations so that the units of observation are appropriate.

The resulting object is still in long format.

# A tibble: 4 x 3
  Demographic  Year  Number
  <chr>       <dbl>   <dbl>
1 Male         2009  577000
2 Male         2018  946000
3 Female       2009 1377000
4 Female       2018 2537000

To conduct a chi-squared test for indepence we will need a contingency table.

A contingency table can be produced from data in long format by transforming the data to wide format and repurposing some values as row names.

The final object should look like this.

       Year2009 Year2018
Male     577000   946000
Female  1377000  2537000

The chi-squared test for independence can be conducted using the stats::chisq.test() function.


    Pearson's Chi-squared test with Yates' continuity correction

data:  chi_square_11.2a
X-squared = 3482.7, df = 1, p-value < 2.2e-16

We can repeat this process for the remaining tables.

       Year2009 Year2018
Male     391000   628000
Female  1013000  1795000

    Pearson's Chi-squared test with Yates' continuity correction

data:  chi_square_11.3a
X-squared = 1696, df = 1, p-value < 2.2e-16
       Year2009 Year2018
Male     168000   351000
Female   505000  1081000

    Pearson's Chi-squared test with Yates' continuity correction

data:  chi_square_11.4a
X-squared = 50.256, df = 1, p-value = 1.349e-12

Data Visualization


This is the intentionally terrible plot that requires faceting.

The plots below need to be correctly faceted. Keep in mind that tables 11.2+ must be faceted by demographic group type and not by setting type.

The plots created (after faceting properly) can be used to answer the questions listed at the beginning of the case study. After finalizing the plots, some time should be spent towards framing the visualizations in such a way to underscore how they were used to asnwer the question.

Summary


Suggested Homework


Additional Information


Acknowledgements

We would like to acknowledge Tamar Mendelson for assisting in framing the major direction of the case study.

We would also like to acknowledge the Bloomberg American Health Initiative for funding this work.

LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgOiBNZW50YWwgSGVhbHRoIG9mIEFtZXJpY2FuIFlvdXRoIgpjc3M6IHN0eWxlLmNzcwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwoKLS0tCjxzdHlsZT4KI1RPQyB7CiAgYmFja2dyb3VuZDogdXJsKCJodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vaW1nL2xvZ28uanBnIik7CiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOwogIHBhZGRpbmctdG9wOiAyNDBweCAhaW1wb3J0YW50OwogIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7Cn0KPC9zdHlsZT4KCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChpbmNsdWRlID0gVFJVRSwgY29tbWVudCA9IE5BLCBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBjYWNoZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIsIG91dC53aWR0aCA9ICc5MCUnKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkobWFnaWNrKQpgYGAKCiMjIHsuZGlzY2xhaW1lcl9ibG9ja30KCioqRGlzY2xhaW1lcioqOiBUaGUgcHVycG9zZSBvZiB0aGUgW09wZW4gQ2FzZSBTdHVkaWVzXShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8pe3RhcmdldD0iX2JsYW5rIn0gcHJvamVjdCBpcyAqKnRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdmFyaW91cyBkYXRhIHNjaWVuY2UgbWV0aG9kcywgdG9vbHMsIGFuZCBzb2Z0d2FyZSBpbiB0aGUgY29udGV4dCBvZiBtZXNzeSwgcmVhbC13b3JsZCBkYXRhKiouIEEgZ2l2ZW4gY2FzZSBzdHVkeSBkb2VzIG5vdCBjb3ZlciBhbGwgYXNwZWN0cyBvZiB0aGUgcmVzZWFyY2ggcHJvY2VzcywgaXMgbm90IGNsYWltaW5nIHRvIGJlIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHdheSB0byBhbmFseXplIGEgZ2l2ZW4gZGF0YSBzZXQsIGFuZCBzaG91bGQgbm90IGJlIHVzZWQgaW4gdGhlIGNvbnRleHQgb2YgbWFraW5nIHBvbGljeSBkZWNpc2lvbnMgd2l0aG91dCBleHRlcm5hbCBjb25zdWx0YXRpb24gZnJvbSBzY2llbnRpZmljIGV4cGVydHMuIAoKIyMgey5saWNlbnNlX2Jsb2NrfQoKVGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBDcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uLU5vbkNvbW1lcmNpYWwgMy4wIFsoQ0MgQlktTkMgMy4wKV0oaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLzMuMC91cy8pe3RhcmdldD0iX2JsYW5rIn0gIFVuaXRlZCBTdGF0ZXMgTGljZW5zZS4KCiMjIHsucmVmZXJlbmNlX2Jsb2NrfQoKVG8gY2l0ZSB0aGlzIGNhc2Ugc3R1ZHkgcGxlYXNlIHVzZToKCldyaWdodCwgQ2FycmllLCBhbmQgT250aXZlcm9zLCBNaWNoYWVsIGFuZCBKYWdlciwgTGVhaCBhbmQgVGF1YiwgTWFyZ2FyZXQgYW5kIEhpY2tzLCBTdGVwaGFuaWUuICgyMDIwKS4gaHR0cHM6Ly9naXRodWIuY29tL29wZW5jYXNlc3R1ZGllcy9vY3MtYnAtY28yLWVtaXNzaW9ucy4gTWVudGFsIEhlYWx0aCBvZiBBbWVyaWNhbiBZb3V0aCAoVmVyc2lvbiB2MS4wLjApLgoKCiMjICoqTW90aXZhdGlvbioqCioqKiAKClRoZSBmb2xsb3dpbmcgcGFwZXJzIG1vdGl2YXRlZCB0aGlzIGNhc2Ugc3R1ZHkuIAoKIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30KClR3ZW5nZSBKTSwgQ29vcGVyIEFCLCBKb2luZXIgVEUsIER1ZmZ5IE1FLCBCaW5hdSBTRy4gQWdlLCBwZXJpb2QsIGFuZCBjb2hvcnQgdHJlbmRzIGluIG1vb2QgZGlzb3JkZXIgaW5kaWNhdG9ycyBhbmQgc3VpY2lkZS1yZWxhdGVkIG91dGNvbWVzIGluIGEgbmF0aW9uYWxseSByZXByZXNlbnRhdGl2ZSBkYXRhc2V0LCAyMDA1LTIwMTcuICpKIEFibm9ybSBQc3ljaG9sKi4xMjgsMyAoMjAxOSk6MTg1LTE5OS4gZG9pOjEwLjEwMzcvYWJuMDAwMDQxMAoKCk9sZnNvbiwgTS4sIEJsYW5jbywgQy4sIFdhbmcsIFMuLCBMYWplLCBHLiAmIENvcnJlbGwsIEMuIFUuIE5hdGlvbmFsIFRyZW5kcyBpbiB0aGUgTWVudGFsIEhlYWx0aCBDYXJlIG9mIENoaWxkcmVuLCBBZG9sZXNjZW50cywgYW5kIEFkdWx0cyBieSBPZmZpY2UtQmFzZWQgUGh5c2ljaWFucy4gKkpBTUEgUHN5Y2hpYXRyeSouIDcxLCA4MSAoMjAxNCk6ODEtOTAuIGRvaTogMTAuMTAwMS9qYW1hcHN5Y2hpYXRyeS4yMDEzLjMwNzQuCgojIyMjCgpUaGUgbWFpbiBmaW5kaW5ncyBvZiB0aGUgZmlyc3QgW2FydGljbGVdKGh0dHBzOi8vY29udGVudC5hcGEub3JnL3JlY29yZC8yMDE5LTEyNTc4LTAwMSl7dGFyZ2V0PSJfYmxhbmsifSBhcmU6Cgo+UmF0ZXMgb2YgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlIGluIHRoZSBsYXN0IHllYXIgaW5jcmVhc2VkIDUyJSAyMDA14oCTMjAxNyAoZnJvbSA4LjclIHRvIDEzLjIlKSBhbW9uZyBhZG9sZXNjZW50cyBhZ2VkIDEyIHRvIDE3IGFuZCA2MyUgMjAwOeKAkzIwMTcgKGZyb20gOC4xJSB0byAxMy4yJSkgYW1vbmcgeW91bmcgYWR1bHRzIDE44oCTMjUuIAoKPlNlcmlvdXMgcHN5Y2hvbG9naWNhbCBkaXN0cmVzcyBpbiB0aGUgbGFzdCBtb250aCBhbmQgc3VpY2lkZS1yZWxhdGVkIG91dGNvbWVzIChzdWljaWRhbCBpZGVhdGlvbiwgcGxhbnMsIGF0dGVtcHRzLCBhbmQgZGVhdGhzIGJ5IHN1aWNpZGUpIGluIHRoZSBsYXN0IHllYXIgYWxzbyBpbmNyZWFzZWQgYW1vbmcgeW91bmcgYWR1bHRzIDE44oCTMjUgZnJvbSAyMDA44oCTMjAxNyAod2l0aCBhIDcxJSBpbmNyZWFzZSBpbiBzZXJpb3VzIHBzeWNob2xvZ2ljYWwgZGlzdHJlc3MpLCB3aXRoIGxlc3MgY29uc2lzdGVudCBhbmQgd2Vha2VyIGluY3JlYXNlcyBhbW9uZyBhZHVsdHMgYWdlcyAyNiBhbmQgb3Zlci4gCgo+Q3VsdHVyYWwgdHJlbmRzIGNvbnRyaWJ1dGluZyB0byBhbiBpbmNyZWFzZSBpbiBtb29kIGRpc29yZGVycyBhbmQgc3VpY2lkYWwgdGhvdWdodHMgYW5kIGJlaGF2aW9ycyBzaW5jZSB0aGUgbWlkLTIwMDBzLCBpbmNsdWRpbmcgdGhlIHJpc2Ugb2YgZWxlY3Ryb25pYyBjb21tdW5pY2F0aW9uIGFuZCBkaWdpdGFsIG1lZGlhIGFuZCBkZWNsaW5lcyBpbiBzbGVlcCBkdXJhdGlvbiwgbWF5IGhhdmUgaGFkIGEgbGFyZ2VyIGltcGFjdCBvbiB5b3VuZ2VyIHBlb3BsZSwgY3JlYXRpbmcgYSBjb2hvcnQgZWZmZWN0LgoKV2hpbGUgdGhlIG1haW4gZmluZGluZ3Mgb2YgdGhlIHNlY29uZCBbYXJ0aWNsZV0oaHR0cHM6Ly9wdWJtZWQubmNiaS5ubG0ubmloLmdvdi8yNDI4NTM4Mi8pe3RhcmdldD0iX2JsYW5rIn0gYXJlOgoKPkNvbXBhcmVkIHdpdGggYWR1bHQgbWVudGFsIGhlYWx0aCBjYXJlLCB0aGUgbWVudGFsIGhlYWx0aApjYXJlIG9mIHlvdW5nIHBlb3BsZSBoYXMgaW5jcmVhc2VkIG1vcmUgcmFwaWRseS4KCj5CZXR3ZWVuIDE5OTUtMTk5OCBhbmQgMjAwNy0yMDEwLCB2aXNpdHMgcmVzdWx0aW5nIGluIG1lbnRhbCBkaXNvcmRlciBkaWFnbm9zZXMKcGVyIDEwMCBwb3B1bGF0aW9uIGluY3JlYXNlZCBzaWduaWZpY2FudGx5IGZhc3RlciBmb3IgeW91dGhzIChmcm9tIDcuNzggdG8gMTUuMzAgdmlzaXRzKSB0aGFuIGZvcgphZHVsdHMgKGZyb20gMjMuMjMgdG8gMjguNDggdmlzaXRzKSAoaW50ZXJhY3Rpb246IFAgPCAuMDAxKS4gCgo+UHN5Y2hpYXRyaXN0IHZpc2l0cyBhbHNvIGluY3JlYXNlZApzaWduaWZpY2FudGx5IGZhc3RlciBmb3IgeW91dGhzIChmcm9tIDIuODYgdG8gNS43MSB2aXNpdHMpLgoKCldoaWxlIGRlcHJlc3Npb24gYXBwZWFyIHRvIGJlIG9uIHRoZSByaXNlIGZvciB5b3V0aHMsIHlvdXRocyBhbHNvIGFwcGVhciB0byBiZSBzZWVraW5nIG1vcmUgbWVudGFsIGhlYWx0aCBjYXJlLgoKSW4gdGhpcyBjYXNlIHN0dWR5IHdlIHdpbGwgZXZhbHVhdGUgZGF0YSByZWxhdGVkIHRvIGRlcHJlc3Npb24gZXBpc29kZXMgYW5kIG1lbnRhbCBoZWFsdGggY2FyZSB0byBldmFsdWF0ZSB0cmVuZHMgb3ZlcnRpbWUuIFdlIHdpbGwgYmUgdXNpbmcgZGF0YSBmcm9tIHRoZSBbTmF0aW9uYWwgU3VydmV5IG9uIERydWcgVXNlIGFuZCBIZWFsdGggKE5TRFVIKV0oaHR0cHM6Ly9uc2R1aHdlYi5ydGkub3JnL3Jlc3B3ZWIvaG9tZXBhZ2UuY2ZtKS4gVGhpcyBkYXRhIHdhcyBhbHNvIHVzZWQgaW4gdGhlIGZpcnN0IHN0dWR5LiAgCgoKIyMgKipNYWluIFF1ZXN0aW9ucyoqCioqKiAKCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb25zOiA8L3U+PC9iPgoKMSkgSG93IGhhdmUgZGVwcmVzc2lvbiByYXRlcyBpbiBBbWVyaWNhbiB5b3V0aCBjaGFuZ2VkIHNpbmNlIDIwMDIsIGFjY29yZGluZyB0byB0aGUgTlNEVUggZGF0YT8gIAoyKSBEbyBtZW50YWwgaGVhbHRoIHNlcnZpY2VzIGFwcGVhciB0byBiZSByZWFjaGluZyBtb3JlIHlvdXRocz8gSG93IGhhdmUgcmF0ZXMgZGlmZmVyZWQgYmV0d2VlbiBkaWZmZXJlbnQgeW91dGggc3ViZ3JvdXBzIChnZW5kZXIsIGV0aG5pY2l0eSk/CgojIyMjCgojIyAqKkxlYXJuaW5nIE9iamVjdGl2ZXMqKiAKKioqIAoKYXZvY2FkbyB1cGRhdGUgdGhlc2UhCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipJdCBtYXkgYmUgYSBnb29kIGlkZWEgdG8gcHJvdmlkZSBhIGxpbmsgdG8gUnN0dWRpbydzIHdlYnBhZ2UuIEZvciB0aGUgZmlyc3QgZmV3IG1vbnRocyB1c2luZyBSLCBJIGRpZCBub3QgZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIFIgYW5kIFIgU3R1ZGlvLiBJdCBtYXkgYmUgYSBnb29kIGRpc3RpbmN0aW9uIHRvIG1ha2UgYXQgbGVhc3QgaW1wbGljaXRseSBieSBwcm92aWRpbmcgYSBsaW5rLioqCgo8L2Rpdj4KCkluIHRoaXMgY2FzZSBzdHVkeSwgd2Ugd2lsbCBkZXRlcm1pbmUgdGhlIHBlcmNlbnQgb2YgeW91dGggaW4gQW1lcmljYSB0aGF0IGhhdmUgaGFkIGEgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlIGluIHRoZSBwYXN0IHllYXIgc2luY2UgMjAwMi4gV2Ugd2lsbCBjb21wYXJlIGhvdyBkaWZmZXJlbnQgeW91dGggc3ViZ3JvdXBzIGhhdmUgY2hhbmdlZCBvdmVyIHRpbWUgKGJ5IGFnZSBncm91cCAoMTItMTMsMTQtMTUsIGFuZCAxNi0xNyksIGdlbmRlciwgZXRobmljaXR5KS4KV2Ugd2lsbCBlc3BlY2lhbGx5IGZvY3VzIG9uIHVzaW5nIHBhY2thZ2VzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgW2BUaWR5dmVyc2VgXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSwgc3VjaCBhcyBbYHJ2ZXN0YF0oaHR0cHM6Ly9naXRodWIuY29tL3RpZHl2ZXJzZS9ydmVzdCkuIFRoZSB0aWR5dmVyc2UgaXMgYSBsaWJyYXJ5IG9mIHBhY2thZ2VzIGNyZWF0ZWQgYnkgUlN0dWRpby4gV2hpbGUgc29tZSBzdHVkZW50cyBtYXkgYmUgZmFtaWxpYXIgd2l0aCBwcmV2aW91cyBSIHByb2dyYW1taW5nIHBhY2thZ2VzLCB0aGVzZSBwYWNrYWdlcyBtYWtlIGRhdGEgc2NpZW5jZSBpbiBSIGVzcGVjaWFsbHkgZWZmaWNpZW50LgoKYGBge3IsIG91dC53aWR0aCA9ICIyMCUiLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9CmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vdGlkeXZlcnNlLnRpZHl2ZXJzZS5vcmcvbG9nby5wbmciKQpgYGAKCioqKiAKCldlIHdpbGwgYmVnaW4gYnkgbG9hZGluZyB0aGUgcGFja2FnZXMgdGhhdCB3ZSB3aWxsIG5lZWQ6CgpgYGB7cn0KbGlicmFyeShoZXJlKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShydmVzdCkKYGBgCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqSSBtYWRlIHNvbWUgbW9kaWZpY2F0aW9ucyB0byB0aGUgdGFibGUgYmVsb3cuIFRoZSBgdGlkeXZlcnNlYCBwYWNrYWdlIGh5cGVybGluayByZWZlcmVuY2VkIGByZWFkcmAuIEkgdGhvdWdodCB0aGlzIHdhcyBpbmNvcnJlY3QuIEkgY2hhbmdlZCB0aGlzIHRvIHRoZSB0aWR5dmVyc2Ugd2Vic2l0ZSBhbmQgcHJvdmlkZWQgYSBkaWZmZXJlbnQgZGVzY3JpcHRpb24uIElmIHRoaXMgd2FzIGluZGVlZCBhIHR5cG8sIGl0IG1heSBuZWVkIHRvIGJlIGZpeGVkIGluIG90aGVyIGNhc2Ugc3R1ZGllcy4qKgoKPC9kaXY+CgogUGFja2FnZSAgIHwgVXNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAotLS0tLS0tLS0tIHwtLS0tLS0tLS0tLS0tCltoZXJlXShodHRwczovL2dpdGh1Yi5jb20vamVubnliYy9oZXJlX2hlcmUpe3RhcmdldD0iX2JsYW5rIn0gICAgICAgfCB0byBlYXNpbHkgbG9hZCBhbmQgc2F2ZSBkYXRhClt0aWR5dmVyc2VdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCBSIHBhY2thZ2VzIGZvciBkYXRhIHNjaWVuY2UKW3J2ZXN0XShodHRwczovL2dpdGh1Yi5jb20vdGlkeXZlcnNlL3J2ZXN0KXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzY3JhcGUgd2ViIHBhZ2VzCgpUaGUgZmlyc3QgdGltZSB3ZSB1c2UgYSBmdW5jdGlvbiwgd2Ugd2lsbCB1c2UgdGhlIGA6OmAgdG8gaW5kaWNhdGUgd2hpY2ggcGFja2FnZSB3ZSBhcmUgdXNpbmcuIFVubGVzcyB3ZSBoYXZlIG92ZXJsYXBwaW5nIGZ1bmN0aW9uIG5hbWVzLCB0aGlzIGlzIG5vdCBuZWNlc3NhcnksIGJ1dCB3ZSB3aWxsIGluY2x1ZGUgaXQgaGVyZSB0byBiZSBpbmZvcm1hdGl2ZSBhYm91dCB3aGVyZSB0aGUgZnVuY3Rpb25zIHdlIHdpbGwgdXNlIGNvbWUgZnJvbS4KCiMjICoqQ29udGV4dCoqCioqKiAKCkFjY29yZGluZyB0byBvdGhlciBzb3VyY2VzIHRoZSByYXRlIG9mIHN1aWNpZGUgaGFzIGluY3JlYXNlZCBmb3IgbW9zdCBhZ2UgZ3JvdXBzIGluIHRoZSBVbml0ZWQgU3RhdGVzIG92ZXIgdGhlIHBhc3QgZGVjYWRlIGFuZCBhIGhhbGYuCgpgYGB7ciwgb3V0LndpZHRoID0gIjgwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2ltYWdlcy9kYXRhYnJpZWZzLzMwMS0zNTAvZGIzMDlfZmlnMS5wbmciKQpgYGAKCiMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9wcm9kdWN0cy9kYXRhYnJpZWZzL2RiMzA5Lmh0bSlde3RhcmdldD0iX2JsYW5rIn0KCgpXaGlsZSBzdWljaWRlIGRvZXMgYXBwZWFyIHRvIGJlIGluY3JlYXNpbmcgYW1vdW5nIHlvdXRocyBpdCBhbHNvIGFwcGVhcnMgdG8gYmUgaW5jcmVhc2luZyBhbW91bmcgbWlkZGxlIGFnZWQgYWR1bHRzIGFzIHdlbGwgZm9yIGJvdGggZmVtYWxlcyBhbmQgbWFsZXMuIAoKYGBge3IsIG91dC53aWR0aCA9ICI4MCUiLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9CmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9pbWFnZXMvZGF0YWJyaWVmcy8zMDEtMzUwL2RiMzA5X2ZpZzIucG5nIikKYGBgCgojIyMjIFtbc291cmNlXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvcHJvZHVjdHMvZGF0YWJyaWVmcy9kYjMwOS5odG0pXXt0YXJnZXQ9Il9ibGFuayJ9CgoKCgpgYGB7ciwgb3V0LndpZHRoID0gIjgwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2ltYWdlcy9kYXRhYnJpZWZzLzMwMS0zNTAvZGIzMDlfZmlnMy5wbmciKQpgYGAKCiMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9wcm9kdWN0cy9kYXRhYnJpZWZzL2RiMzA5Lmh0bSlde3RhcmdldD0iX2JsYW5rIn0KCgpBY2NvcmRpbmcgdG8gdGhlIFtDRENdKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9wcm9kdWN0cy9kYXRhYnJpZWZzL2RiMzA5Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifToKCj4gU2luY2UgMjAwOCwgc3VpY2lkZSBoYXMgcmFua2VkIGFzIHRoZSAxMHRoIGxlYWRpbmcgY2F1c2Ugb2YgZGVhdGggZm9yIGFsbCBhZ2VzIGluIHRoZSBVbml0ZWQgU3RhdGVzLiBJbiAyMDE2LCBzdWljaWRlIGJlY2FtZSB0aGUgKipzZWNvbmQgbGVhZGluZyBjYXVzZSBvZiBkZWF0aCoqIGFtb25nIHRob3NlIGFnZWQgKioxMOKAkzM0KiogYW5kIHRoZSBmb3VydGggbGVhZGluZyBjYXVzZSBhbW9uZyB0aG9zZSBhZ2VkIDM14oCTNTQuCgoKCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwMHB4In0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwibW9ydGFsaXR5LnBuZyIpKQpgYGAKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9kYXRhL2RhdGFicmllZnMvZGIyOTMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9CgoKCioqU28gYWx0aG91Z2ggc3VjaWRlIGlzIG9uIHRoZSByaXNlIGZvciBtb3N0IGFnZSBncm91cHMsIHN1Y2lkZSBpcyBvbmUgb2YgdGhlIHRvcCB0d28gY29udHJpYnV0b3JzIHRvIGRlYXRoIGZvciB5b3V0aHMuKiogVGh1cyB0aGlzIHdhcnJlbnRzIGZ1cnRoZXIgZXhhbWluYXRpb24gb2YgbWVudGFsIGhlYWx0aCBvZiBBbWVyaWNhbiB5b3V0aHMuCgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsIm1vcnRhbGl0eV9hZ2UucG5nIikpCmBgYAoKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9kYXRhL252c3IvbnZzcjY4L252c3I2OF8wNi01MDgucGRmKQoKCgoqSWYgeW91IGFyZSBoYXZpbmcgdGhvdWdodHMgb2Ygc3VpY2lkZSwgcGxlYXNlIGtub3cgdGhhdCB5b3UgYXJlIG5vdCBhbG9uZS4gSWYgeW91IGFyZSBpbiBkYW5nZXIgb2YgYWN0aW5nIG9uIHN1aWNpZGFsIHRob3VnaHRzLCBjYWxsIDkxMS4gRm9yIHN1cHBvcnQgYW5kIHJlc291cmNlcywgY2FsbCB0aGUgTmF0aW9uYWwgU3VpY2lkZSBQcmV2ZW50aW9uIExpZmVsaW5lIGF0IDEtODAwLTI3My04MjU1IG9yIHRleHQgNzQxLTc0MSBmb3IgdGhlIENyaXNpcyBUZXh0IExpbmUuKgoKSSB0b29rIHRoaXMgZnJvbSBhbiBhcnRpY2xlLmh0dHBzOi8vd3d3LnRoZWF0bGFudGljLmNvbS9oZWFsdGgvYXJjaGl2ZS8yMDIwLzA2L3doeS1zdWljaWRlLXJhdGVzLWFtb25nLW1pbGxlbm5pYWxzLWFyZS1yaXNpbmcvNjEyOTQzLwoKKklmIHlvdSBvciBzb21lb25lIHlvdSBrbm93IG1heSBiZSBzdHJ1Z2dsaW5nIHdpdGggc3VpY2lkYWwgdGhvdWdodHMsIHlvdSBjYW4gY2FsbCB0aGUgVS5TLiBOYXRpb25hbCBTdWljaWRlIFByZXZlbnRpb24gTGlmZWxpbmUgYXQgODAwLTI3My1UQUxLICg4MjU1KSBhbnkgdGltZSBkYXkgb3IgbmlnaHQsIG9yIGNoYXQgb25saW5lLioKSSB0aG9vayB0aG9zIGZyb20gdGhpcyBhcnRpY2xlLiBodHRwczovL3d3dy51c2F0b2RheS5jb20vc3RvcnkvbmV3cy9uYXRpb24vMjAyMC8wMS8zMC91LXMtc3VpY2lkZS1yYXRlLXJvc2UtYWdhaW4tMjAxOC1ob3ctY2FuLXN1aWNpZGUtcHJldmVudGlvbi1zYXZlLWxpdmVzLzQ2MTY0NzkwMDIvCgoKCgpjb3ZpZDpodHRwczovL3dlbGxiZWluZ3RydXN0Lm9yZy9hcmVhcy1vZi1mb2N1cy9wb2xpY3ktYW5kLWFkdm9jYWN5L3JlcG9ydHMvcHJvamVjdGVkLWRlYXRocy1vZi1kZXNwYWlyLWR1cmluZy1jb3ZpZC0xOS8KCkhpc3RvcmljYWxseSwgc3VpY2lkZSByYXRlcyB3ZXJlIG11Y2ggaGlnaGVyIGJlZm9yZSAxOTUwLCBob3dldmVyLCB3ZSBhcmUgc2VlaW5nIGFuIGluY3JlYXNlIGluIHRoZSBsYXN0IDIwIHllYXJzLgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI4MDBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsInN1aWNpZGUucG5nIikpCmBgYAoKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vdGltZS5jb20vNTYwOTEyNC91cy1zdWljaWRlLXJhdGUtaW5jcmVhc2UvKXt0YXJnZXQ9Il9ibGFuayJ9CgoKCgoKQmVzaWRlcyB0aGUgVVMsIFtvdGhlciBjb3VudHJpZXNdKGh0dHBzOi8vYWNhZGVtaWMub3VwLmNvbS9pamUvYXJ0aWNsZS80OC81LzE2NTAvNTM2NjIxMCl7dGFyZ2V0PSJfYmxhbmsifSBhcmUgYWxzbyBleHBlcmllbmNpbmcgaW5jcmVhc2VkIHJlYXRlcyBvZiBkZXByZXNzaW9uIGluIHlvdXRocy4gU2VlIFt0aGlzIHJlcG9ydF0oaHR0cHM6Ly9hcHBzLndoby5pbnQvaXJpcy9iaXRzdHJlYW0vaGFuZGxlLzEwNjY1LzI1NDYxMC9XSE8tTVNELU1FUi0yMDE3LjItZW5nLnBkZjtqc2Vzc2lvbmlkPUU0NDM2MDA1NUREODNFQUM0NzJBQTQwQzI4NTNEQkZBP3NlcXVlbmNlPTEpe3RhcmdldD0iX2JsYW5rIn0gZnJvbSB0aGUgIFdvcmxkIEhlYWx0aCBPcmdhbml6YXRpb24gYWJvdXQgcmF0ZXMgb2YgZGVwcmVzc2lvbiBpbiBvdGhlciBjb3VudHJpZXMuCgpHcmVhdCBwYXBlciBhYm91dCB3aGF0IG1heSBiZSBjYXVzaW5nIGluY3JlYXNlZCBkcHJlc3Npb24gLSBhbmQgdGhlIGNhdmVhdHMgb2YgaWYgd2UgYWN0dWFsbHkgaGF2ZSBpbmNyZWFzZWQgZGVwcmVzc2lvbjogaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DMzMzMDE2MS8KCgoKCmh0dHBzOi8vd3d3Lm5pbWgubmloLmdvdi9oZWFsdGgvcHVibGljYXRpb25zL3RlZW4tZGVwcmVzc2lvbi9pbmRleC5zaHRtbAoKCkFjY29yZGluZyB0byB0aGUgW05hdGlvbmFsIEluc3RpdHV0ZSBvZiBNZW50YWwgSGVhbHRoIChOSU1IKV0oaHR0cHM6Ly93d3cubmltaC5uaWguZ292L2hlYWx0aC9wdWJsaWNhdGlvbnMvdGVlbi1kZXByZXNzaW9uL2luZGV4LnNodG1sKXt0YXJnZXQ9Il9ibGFuayJ9OgoKSWYgeW91IGFyZSBpbiBjcmlzaXMgYW5kIG5lZWQgaGVscCwgY2FsbCB0aGlzIHRvbGwtZnJlZSBudW1iZXIgZm9yIHRoZSBOYXRpb25hbCBTdWljaWRlIFByZXZlbnRpb24gTGlmZWxpbmUgKE5TUEwpLCBhdmFpbGFibGUgMjQgaG91cnMgYSBkYXksIGV2ZXJ5IGRheTogMS04MDAtMjczLVRBTEsgKDgyNTUpLiBUaGUgc2VydmljZSBpcyBhdmFpbGFibGUgdG8gZXZlcnlvbmUuIFRoZSBkZWFmIGFuZCBoYXJkIG9mIGhlYXJpbmcgY2FuIGNvbnRhY3QgdGhlIExpZmVsaW5lIHZpYSBUVFkgYXQgMS04MDAtNzk5LTQ4ODkuIEFsbCBjYWxscyBhcmUgY29uZmlkZW50aWFsLiBZb3UgY2FuIGFsc28gdmlzaXQgdGhlIExpZmVsaW5l4oCZcyB3ZWJzaXRlIGF0IHd3dy5zdWljaWRlcHJldmVudGlvbmxpZmVsaW5lLm9yZy4KClRoZSBDcmlzaXMgVGV4dCBMaW5lIGlzIGFub3RoZXIgZnJlZSwgY29uZmlkZW50aWFsIHJlc291cmNlIGF2YWlsYWJsZSAyNCBob3VycyBhIGRheSwgc2V2ZW4gZGF5cyBhIHdlZWsuIFRleHQg4oCcSE9NReKAnSB0byA3NDE3NDEgYW5kIGEgdHJhaW5lZCBjcmlzaXMgY291bnNlbG9yIHdpbGwgcmVzcG9uZCB0byB5b3Ugd2l0aCBzdXBwb3J0IGFuZCBpbmZvcm1hdGlvbiBvdmVyIHRleHQgbWVzc2FnZS4gVmlzaXQgd3d3LmNyaXNpc3RleHRsaW5lLm9yZy4KCgpBbHNvIHNlZSBbaGVyZV0oaHR0cHM6Ly93d3cubWhhbmF0aW9uYWwub3JnL2RlcHJlc3Npb24tdGVlbnMtMCkgZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgaG93IHRvIHJlY29nbmlzZSBhbmQgaGVscCB5b3V0aHMgZXhwZXJpZW5jaW5nIHN5bXB0b21zIG9mIGRlcHJlc3Npb24uCgojIyAqKkxpbWl0YXRpb25zKioKKioqIAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKlBlcmhhcHMgInVuZGVyZXN0aW1hdGVzIGluIHRoZSBwLXZhbHVlcy4uLiIgaXMgbm90IHRoZSBjb3JyZWN0IHdheSB0byBwaHJhc2UgdGhpcy4gSSB3b3VsZCBsb29rIGZvciBhIGJldHRlciB3YXkgdG8gd29yZCB0aGlzLioqCgo8L2Rpdj4KCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipXb3JkaW5nIGZvciB0aGlzIHNlY3Rpb24gc2hvdWxkIGJlIHJldmlld2VkLioqCgo8L2Rpdj4KClRoZXJlIGFyZSBzb21lIGltcG9ydGFudCBjb25zaWRlcmF0aW9ucyByZWdhcmRpbmcgdGhpcyBkYXRhIGFuYWx5c2lzIHRvIGtlZXAgaW4gbWluZDogCgoxKSBXZSB0cmVhdCBzYW1wbGUgZXN0aW1hdGVz4oCUZXN0aW1hdGVzIG9mIHRoZSB0cnVlIHBvcHVsYXRpb24gdmFsdWXigJRhcyBvYnNlcnZlZCB2YWx1ZXMuIFRoaXMgcHJvZHVjZXMgdW5kZXJzdGltYXRlcyBpbiB0aGUgcC12YWx1ZXMgb2Ygc3RhdGlzdGljYWwgdGVzdHMgY29uZHVjdGVkLgoKMikgRnVydGhlcm1vcmUsIHRoZSBzYW1wbGluZyBtZWNoYW5pc20gdXRpbGl6ZWQgY2FuIGludHJvZHVjZSBbc2VsZWN0aW9uIGJpYXNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NlbGVjdGlvbl9iaWFzP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9IGluIGNhc2VzIHdoZXJlIHRoZSB0aGUgW3NhbXBsaW5nIG1ldGhvZHMgZG8gbm90IHByb2R1Y2UgYSByZXByZXNlbnRhdGl2ZSBzYW1wbGVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhbXBsaW5nXyhzdGF0aXN0aWNzKT9vbGRmb3JtYXQ9dHJ1ZSl7dGFyZ2V0PSJfYmxhbmsifS4gCgozKSBEYXRhIGlzIGNvbGxlY3RlZCBmcm9tIGh1bWFuIHBhcnRpY2lwYW50czsgdGhpcyBwcmVzZW50cyB0aGUgKnBvdGVudGlhbCogZm9yIGluZm9ybWF0aW9uIGJpYXMsIGFzIHRoZXJlIGlzIHRoZSAqcG90ZW50aWFsKiB0aGF0IHBhcnRpZmljaXBhbnRzIGluIHRoZSBbc2FtcGxpbmcgZnJhbWVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhbXBsaW5nX2ZyYW1lP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9IG1heSBmb3IgYSB2YXJpZXR5IG9mIHJlYXNvbnMgcmVwb3J0IGluYWNjdXJhdGUgaW5mb3JtYXRpb24uIAoKIyMgKipXaGF0IGFyZSB0aGUgZGF0YT8qKgoqKiogCgpXZSB3aWxsIGJlIHVzaW5nIGRhdGEgZnJvbSB0aGUgW05hdGlvbmFsIFN1cnZleSBvbiBEcnVnIFVzZSBhbmQgSGVhbHRoIChOU0RVSCldKGh0dHBzOi8vbnNkdWh3ZWIucnRpLm9yZy9yZXNwd2ViL2hvbWVwYWdlLmNmbSl7dGFyZ2V0PSJfYmxhbmsifSB3aGljaCBpcyBkaXJlY3RlZCBieSB0aGUgW1N1YnN0YW5jZSBBYnVzZSBhbmQgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBBZG1pbmlzdHJhdGlvbiAoU0FNSFNBKV0oaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0sIGFuIGFnZW5jeSBpbiB0aGUgW1UuUy4gRGVwYXJ0bWVudCBvZiBIZWFsdGggYW5kIEh1bWFuIFNlcnZpY2VzIChESEhTKV0oaHR0cHM6Ly93d3cuaGhzLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0uIAoKVGhpcyBzdXJ2ZXkgc3RhcnRlZCBpbiAxOTcxIGFuZCBpcyBjb25kdWN0ZWQgYW5udWFseSBpbiBhbGwgNTAgc3RhdGVzIGFuZCB0aGUgRGlzdHJpY3Qgb2YgQ29sdW1iaWEuIEFwcHJveGltYXRlbHkgNzAsMDAwIHBlb3BsZSAoYWdlIDEyIGFuZCB1cCkgYXJlIGludGVydmlld2VkIGVhY2ggeWVhciBhYm91dCBoZWFsdGggcmVhbHRlZCBpc3N1ZXMuIEhvdXNlaG9sZHMgYXJlIHJhbmRvbWx5IHNlbGVjdGVkIGFuZCB0aGFuIGEgcHJvZmVzc2lvbmFsIGludGVydmlld2VyIHZpc2lzdHMgdGhlIGFkZHJlc3NlcyBhbmQgYXNrcyBvbmUgb3IgdHdvIG9mIHRoZSByZXNpZGVudHMgdG8gaW52ZXJ2aWV3LiBUaGUgaW50ZXJ2aWV3ZXIgYnJpbmdzIGEgbGFwdG9wIHdpdGggdGhlbSB0aGF0IHRoZSBwYXJ0aWNpcGFudHMgdXNlIHRvIGZpbGwgb3V0IHRoZSBzdXJ2ZXkgd2hpY2ggdHlwaWNhbGx5IHRha2VzIGFuIGhvdXIgdG8gY29tcGxldGUuIElmIGEgcGFydGljaXBhbnQgY2hvb3NlcyB0byBwYXJ0aWNwYXRlIHRoZXkgcmVjZWl2ZSAkMzAgaW4gY2FzaC4gQWxsIGNvbGxlY3RlZCBpbmZvcm1hdGlvbiBpcyBjb25maWRlbnRpYWwgYW5kIGlzIHVzZWQgZm9yIGRpc2Vhc2Ugc3VydmVpbGxhbmNlIGFuZCB0byBndWlkZSBwdWJsaWMgcG9saWN5IHBhcnRpY3VhcmxseSBmb2N1c2VkIG9uIGRydWcgYW5kIGFsY29ob2wgdXNlIGFzIHdlbGwgYXMgbWVudGFsIGhlYWx0aC4gU2VlIFtoZXJlXShodHRwczovL25zZHVod2ViLnJ0aS5vcmcvcmVzcHdlYi9hYm91dF9uc2R1aC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGRldGFpbHMgYWJvdXQgdGhlIHN1cnZleS4KClRoaXMgZGF0YSBpcyBtYWRlIGF2YWlsYWJsZSBwdWJsaWNseSBvbmxpbmUgb24gdGhlIFtTdWJzdGFuY2UgQWJ1c2UgJiBNZW50YWwgSGVhbHRoIERhdGEgQXJjaGl2ZV0oaHR0cHM6Ly9kYXRhZmlsZXMuc2FtaHNhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0uIAoKYGBge3IsIG91dC53aWR0aCA9ICIxMDAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJuc3VkaF9zY3JlZW5zaG90X3dlYnBhZ2UucG5nIikpCmBgYAoKQXQgdGhlIFt3ZWJzaXRlXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pe3RhcmdldD0iX2JsYW5rIn0gZm9yIHRoZSBzdXJ2ZXkgZGF0YSwgeW91IGNhbiBzZWUgdGhhdCB0aGUgcmVzdWx0cyBhcmUgZGlzcGxheWVkIGluIG1hbnkgdGFibGVzLiBJbXBvcnRhbnRseSwgdGhlcmUgaXMgbm8gb2J2aW91cyB3YXkgdG8gZG93bmxvYWQgdGhlIGRhdGEgZGlyZWN0bHkgZnJvbSB0aGlzIHBhcnRpY3VsYXIgd2Vic2l0ZS4KCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAid2Vic2l0ZV9vdmVydmlldy5wbmciKSkKYGBgCgpJZiBvbmUgY2xpY2tzIG9uIHRoZSBUT0MgYm90dG9uIG9uIHRoZSBmYXIgcmlnaHQgdXBwZXIgY29ybmVyIHRoZXkgd2lsbCBiZSBkaXJlY3RlZCB0byBhbm90aGVyIFt3ZWJzaXRlXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0YWlsZWRUYWJzVE9DMjAxOC5odG0jdG9jKXt0YXJnZXQ9Il9ibGFuayJ9LCB3aGVyZSBhIGxhcmdlIFtwZGYgZG9jdW1lbnRdKGh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL2NiaHNxLXJlcG9ydHMvTlNEVUhEZXRhaWxlZFRhYnMyMDE4UjIvTlNEVUhEZXRhaWxlZFRhYnMyMDE4LnBkZil7dGFyZ2V0PSJfYmxhbmsifSBjb250YWluaW5nIG9mIGFsbCBvZiB0aGUgcmVzdWx0cyBjYW4gYmUgZG93bmxvYWRlZC4KCldlIGFyZSBpbnRlcmVzdGVkIGluIGludmVzdGlnYXRpbmcgaG93IGRlcHJlc3Npb24gcmF0ZXMgaGF2ZSBjaGFuZ2VkIGFuZCBob3cgeW91dGhzIGFyZSBpbnRlcmFjdGluZyB3aXRoIG1lbnRhbCBoZWFsdGggc2VydmljZXMuIFRodXMgdGhlIGZvbGxvd2luZyB0YWJsZXMgYXJlIG9mIGludGVyZXN0IHRvIHVzIGFyZToKClRhYmxlICAgfCBEZXRhaWxzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAotLS18LS0tLS0tLS0tLS0tLQpUYWJsZSAxMS4xQSAgICAgICB8IFNldHRpbmdzIFdoZXJlIE1lbnRhbCBIZWFsdGggU2VydmljZXMgV2VyZSBSZWNlaXZlZCBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3OiBOdW1iZXJzIGluIFRob3VzYW5kcywgMjAwMi0yMDE4ICAgClRhYmxlIDExLjFCICAgICAgIHwgU2V0dGluZ3MgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBXZXJlIFJlY2VpdmVkIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTc6IFBlcmNlbnRhZ2VzLCAyMDAyLTIwMTggIApUYWJsZSAxMS4yQSAgICAgICB8ICBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNywgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBOdW1iZXJzIGluIFRob3VzYW5kcywgMjAwNC0yMDE4ClRhYmxlIDExLjJCICAgICAgIHwgTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcsIGJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDQtMjAxOApUYWJsZSAxMS4zQSAgICAgICB8IE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSB3aXRoIFNldmVyZSBJbXBhaXJtZW50IGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcsIGJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogTnVtYmVycyBpbiBUaG91c2FuZHMsIDIwMDYtMjAxOApUYWJsZSAxMS4zQiAgICAgICB8IE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSB3aXRoIFNldmVyZSBJbXBhaXJtZW50IGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcsIGJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDYtMjAxOApUYWJsZSAxMS40QSAgICAgICB8IFJlY2VpcHQgb2YgVHJlYXRtZW50IGZvciBEZXByZXNzaW9uIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcgd2l0aCBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyLCBieSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IE51bWJlcnMgaW4gVGhvdXNhbmRzLCAyMDA0LTIwMTgKVGFibGUgMTEuNEIgICAgICAgfCBSZWNlaXB0IG9mIFRyZWF0bWVudCBmb3IgRGVwcmVzc2lvbiBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IHdpdGggTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhciwgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNC0yMDE4CgoKIyMjIwoKIyMgKipEYXRhIEltcG9ydCoqCioqKiAKCkRhdGEgaXMgb2Z0ZW4gbWFkZSBhdmFpbGFibGUgb25saW5lLiBVc3VhbGx5LCB0aGUgZGF0YSB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBpcyBtYWRlIGF2YWlsYWJsZSBmb3IgZG93bmxvYWQgb24gdGhlIHBhZ2UgYXMgYSBkZWxpbWl0ZWQgdGV4dCBmaWxlIG9yIGFuIGV4Y2VsIGZpbGUuIEhvd2V2ZXIsIHNvbWV0aW1lcyBkYXRhIGlzIG5vdCBtYWRlIGF2YWlsYWJsZSBpbiB0aGlzIG1hbm5lciwgc3VjaCBhcyB0aGUgW05TRFVIIHN1cnZleSBkYXRhXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pe3RhcmdldD0iX2JsYW5rIn0uCgpIb3cgZG8gd2UgcHJvY2VlZCBpbiB0aGlzIHNjZW5hcmlvPwoKV2UgY2FuIG1hbnVhbGx5IGNvcHkgZWFjaCBjZWxsIG9mIGRhdGEsIGhvd2V2ZXIsIHRoaXMgcHJvY2VzcyBpcyBvZnRlbiBpbmVmZmljaWVudCwgc3ViamVjdCB0byBlcnJvciwgYW5kIG5vdCByZXByb2R1Y2libGUuIFNheSB3ZSB3YW50ZWQgdG8gcnVuIGFuIGFuYWx5c2lzIG5leHQgeWVhciBvbiB0aGUgbmV4dCB5ZWFycyBkYXRhIGFuZCBpdCBoYXBwZW5zIHRvIGJlIGZvcm1hdHRlZCBpbiB0aGUgc2FtZSB3YXkuIAoKV2UgY2FuIGFsc28gdXNlIGBSYCBmb3Igd2ViIHNjcmFwaW5nLiAKCltXZWIgc2NyYXBpbmddKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dlYl9zY3JhcGluZz9vbGRmb3JtYXQ9dHJ1ZSl7dGFyZ2V0PSJfYmxhbmsifSBpcyB0aGUgcHJvY2VzcyBvZiBleHRyYWN0aW5nIGRhdGEgZnJvbSBhIHdlYnNpdGUuCgoKIyMjIEJhc2ljIHN0ZXBzIG9mIHdlYiBzY3JhcGluZwoKVGhlcmUgYXJlIHR3byBtYWluIHN0ZXBzIHRvIHdlYiBzY3JhcGluZzogIAoKMS4gSWRlbnRpZnkgbG9jYXRpb24gb2YgZGF0YSBvbiB0aGUgd2VicGFnZSB0aGF0IHdpbGwgYmUgc2NyYXBlZCAgCgoyLiBTYXZlIHRoZSB3ZWJwYWdlIGVsZW1lbnQgdG8gYW4gb2JqZWN0ICAKCldlIGFjY29tcGxpc2ggU1RFUCAxIHdpdGggb3VyIHdlYiBicm93c2VyLgoKV2UgYWNjb21wbGlzaCBTVEVQIDIgaW4gdGhlIGBSYCBwcm9ncmFtbWluZyBlbnZpcm9ubWVudC4gCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqSSBjb3VsZCBub3QgZmluZCB0aGUgYW5pbWF0aW9uIHRoYXQgSSByZWZlcnJlZCB0byBvbiBzZXZlcmFsIG9jY2FzaW9ucy4qKgoKKipIb3dldmVyLCBJIHdhcyBhYmxlIHRvIGZpbmQgdGhlIHNvdXJjZXMgdGhhdCBJIGNvbnN1bHRlZCB0byBjcmVhdGUgdGhlIHRocmVlIHN0ZXAgYHJ2ZXN0YCBwcm9jZXNzLiBUaGV5IGFyZSBpbmNsdWRlZCBiZWxvdyoqCgpbUlN0dWRpb10oaHR0cHM6Ly9yc3R1ZGlvLXB1YnMtc3RhdGljLnMzLmFtYXpvbmF3cy5jb20vMjY2NDMwX2YzZmQ0NjYwYjI3NDQ3NTFhYjE0NGFhMTMwNzY4YTA2Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0KCltCbG9nXShodHRwOi8vYmxvZy5jb3J5bmlzc2VuLmNvbS8yMDE1LzAxL3VzaW5nLXJ2ZXN0LXRvLXNjcmFwZS1odG1sLXRhYmxlLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0KCjwvZGl2PgoKSW4gdGhpcyBjYXNlIHN0dWR5IHdlIHdpbGwgc2NyYXBlIGRhdGEgZnJvbSB0aGUgdGFibGVzIG9uIHRoZSBbTlNEVUggc3VydmV5XShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pe3RhcmdldD0iX2JsYW5rIn0gd2Vic2l0ZS4gVGhpcyBkYXRhIGlzIGF2YWlsYWJsZSBpbiBhIGxhcmdlIFBERiB3aXRoIGFsbCB0aGUgcmVzdWx0cyBmb3JtIHRoZSB5ZWFyLiBIb3dldmVyIGl0IGlzIG5vdCBlYXN5IHRvIGZpbmQgdGhpcyBQREYgYW5kIGl0IHdvdWxkIGJlIGRpZmZpY3VsdCBhbmQgdGltZSBjb25zdW1pbmcgdG8gZmluZCBvdXIgdGFibGVzIG9mIGludGVyZXN0IGFuZCB0byBleHRyYWN0IHRoZSBkYXRhIGZyb20gdGhlIHBkZiB3aXRoIGBwZGZ0b29sc2AuIEFnYWluLCBpZiB3ZSBpbnN0ZWFkIGRlY2lkZWQgdG8gY29weSBwYXN0ZSB0aGUgZGF0YSBmcm9tIHRoZSB3ZWJzaXRlIHRvIGFub3RoZXIgZmlsZSB0aGF0IHdlIHdvdWxkIGFsc28gbmVlZCB0byBpbXBvcnQsIHRoaXMgd291bGQgbm90IGJlIGFzIGVmZmljaWVudCBvciByZXByb2R1Y2libGUgYW5kIG1pZ2h0IHJlc3VsdCBpbiBlcnJvcnMuIAoKCkFsdGVybmF0aXZlbHksIHdlIHdpbGwgdXNlIHRoZSBgcnZlc3RgIHBhY2thZ2UgdG8gW3NjcmFwZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV2ViX3NjcmFwaW5nP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9IHRoZSBkYXRhIGRpcmVjdGx5IGZyb20gdGhlIHRhYmxlcyBvbiB0aGUgd2Vic2l0ZS4gQXNzdW1pbmcgdGhlIGRhdGEgbmV4dCB5ZWFyIHdvdWxkIGJlIGRpc3BsYXllZCBpbiBhIHNpbWlsYXIgbWFubmVyLCB0aGlzIGNvdWxkIGFsbG93IHVzIHNpbXBseSBtb2RpZnkgb3VyIGNvZGUgYmFzZWQgb24gdGhlIHVybCBmb3IgdGhlIGRhdGEgbmV4dCB5ZWFyIHRvIHJ1biB0aGUgc2FtZSBhbmFseXNpcyBvbiB0aGUgZGF0YSBlYXNpbHkuIAoKVGhlIGBydmVzdGAgIHBhY2thZ2UgY2FuIGJlIHRob3VnaHQgb2YgYXMgdGhlIGBwZGZ0b29sc2AgcGFja2FnZSBmb3Igd2Vic2NyYXBpbmcuIFVwb24gcHVsbGluZyB0aGUgZGF0YSwgYWRkaXRpb25hbCB3cmFuZ2xpbmcgd2lsbCBsaWtlbHkgYmUgcmVxdWlyZWQ7IGJ1dCBsaWtlIHRoZSBgcGRmdG9vbHNgIHBhY2thZ2UsIGBydmVzdGAgc3RyZWFtbGluZXMgdGhlIGV4dHJhY3Rpb24gcHJvY2Vzcy4gIAoKIyMjIFN0ZXBzIGZvciBzY3JhcGluZyB0YWJsZXMKClRoZSB0d28gd2ViIHNjcmFwaW5nIHN0ZXBzIGZvciB0aGVzZSB0YWJsZXMgY2FuIGJlIGJyb2tlbiBkb3duIGV2ZW4gZnVydGhlcjogCgoxKSBJZGVudGlmeSBsb2NhdGlvbiBvZiBkYXRhIHRoYXQgd2lsbCBiZSBzY3JhcGVkCgorIHJpZ2h0LWNsaWNrIHRvIGluc3BlY3QgZWxlbWVudCAod2VicGFnZSkKKyBob3ZlciBwb2ludGVyIG92ZXIgY29tcG9uZW50cyBvZiBlbGVtZW50ICh3ZWJwYWdlKSB1bnRpbCB0aGUgZGF0YSBoYXMgYmVlbiBmb3VuZAorIGNvcHkgWHBhdGggb2YgZGF0YSBzb3VnaHQKCjIpIFNhdmUgd2VicGFnZSBlbGVtZW50IHRvIGFuIG9iamVjdCBpbiBSCgorIGltcG9ydCBodG1sIGNvZGUgZm9yIHRoZSB3ZWJwYWdlCisgZXh0cmFjdCBwaWVjZXMgb2YgSFRNTCBkb2N1bWVudHMgKHdlYnBhZ2UpIHVzaW5nIFhwYXRoCisgcGFyc2UgdGhlIGV4dHJhY3RlZCBkYXRhIGludG8gYSBkYXRhIGZyYW1lCgpCZWxvdyBpcyBhIGFuaW1hdGVkIG92ZXJ2aWV3IG9mIHRoZSBwcm9jZXNzLgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Kc3RlcDEgPC0gaW1hZ2VfcmVhZChoZXJlOjpoZXJlKCJpbWciLCAid2VicGFnZV9zY3JlZW5zaG90LnBuZyIpKQpzdGVwMiA8LSBpbWFnZV9yZWFkKGhlcmU6OmhlcmUoImltZyIsICJ0YWJsZV9zY3JlZW5zaG90X2luc3BlY3QucG5nIikpCnN0ZXAzIDwtIGltYWdlX3JlYWQoaGVyZTo6aGVyZSgiaW1nIiwgInRhYmxlX3NjcmVlbnNob3RfaW5zcGVjdF90YWJsZS5wbmciKSkKc3RlcDQgPC0gaW1hZ2VfcmVhZChoZXJlOjpoZXJlKCJpbWciLCAidGFibGVfc2NyZWVuc2hvdF9pbnNwZWN0X3RhYmxlX3hwYXRoLnBuZyIpKQpzdGVwNSA8LSBpbWFnZV9yZWFkKGhlcmU6OmhlcmUoImltZyIsICJ0YWJsZV9zY3JlZW5zaG90X3hwYXRoX2NvcHlfci5wbmciKSkKc3RlcDVfem9vbSA8LSBpbWFnZV9yZWFkKGhlcmU6OmhlcmUoImltZyIsICJ0YWJsZV9zY3JlZW5zaG90X3hwYXRoX2NvcHlfcl96b29tLnBuZyIpKQpgYGAKCmBgYHtyLCBldmFsPUZBTFNFLCBlY2hvPUZBTFNFfQppbWFnZV9pbmZvKHN0ZXA1X3pvb20pCgpzdGVwNV96b29tIDwtIGltYWdlX2JvcmRlcihzdGVwNV96b29tLCAid2hpdGUiLCAiMjg0eDMzNCIpCgppbWcgPC0gYyhzdGVwMSwKICAgICAgICAgc3RlcDIsCiAgICAgICAgIHN0ZXAyLAogICAgICAgICBzdGVwMywKICAgICAgICAgc3RlcDMsCiAgICAgICAgIHN0ZXA0LAogICAgICAgICBzdGVwNCwKICAgICAgICAgc3RlcDUsCiAgICAgICAgIHN0ZXA1LAogICAgICAgICBzdGVwNV96b29tLAogICAgICAgICBzdGVwNV96b29tLAogICAgICAgICBzdGVwNV96b29tLAogICAgICAgICBzdGVwMSkKCmVkdWNhdGlvbmFsX2dpZiA8LSBpbWFnZV9yZXNpemUoaW1nLCAnMTQ0MHg5MDAhJykgJT4lCiAgaW1hZ2VfYmFja2dyb3VuZCgnd2hpdGUnKSAlPiUKICBpbWFnZV9tb3JwaChmcmFtZXMgPSAxMCkgJT4lCiAgaW1hZ2VfYW5pbWF0ZShkZWxheSA9IDIwLAogICAgICAgICAgICAgICAgb3B0aW1pemUgPSBUUlVFKQoKaW1hZ2Vfd3JpdGUoZWR1Y2F0aW9uYWxfZ2lmLCBoZXJlOjpoZXJlKCJpbWciLCAiZWR1Y2F0aW9uYWwuZ2lmIikpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsImVkdWNhdGlvbmFsLmdpZiIpKQpgYGAKCioqKgoKTm93IGxldCdzIGdvIHRocm91Z2ggZWFjaCBzdGVwIHRvZ2V0aGVyOgoKIyMjIDEpIElkZW50aWZ5IGxvY2F0aW9uIG9mIGRhdGEgdGhhdCB3aWxsIGJlIHNjcmFwZWQKCkZpcnN0LCBsZXQncyBnbyB0byB0aGUgW3dlYiBwYWdlXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pe3RhcmdldD0iX2JsYW5rIn0gd2l0aCBhbGwgdGhlIHRhYmxlcyB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBzY3JhcGluZwoKYGBge3IsIHN0ZXAxLCBlY2hvPUZBTFNFfQpzdGVwMQpgYGAKCk9uY2Ugb24gdGhlIHdlYnBhZ2UsIHRoZXJlIGFyZW4ndCBhbnkgdmlzaWJsZSBvcHRpb25zIHRvIGRvd25sb2FkIHRoZSBkYXRhLiAKClJpZ2h0LWNsaWNrIGFuZCBzZWxlY3QgIkluc3BlY3QiIAoKYGBge3IsIHN0ZXAyLCBlY2hvPUZBTFNFfQpzdGVwMgpgYGAKCkEgd2luZG93IG9wZW5zLiAKClRoaXMgd2luZG93IGFsbG93cyB1cyB0byBnbGFuY2UgYXQgdGhlIGludGVybmFsIG1lY2hhbmljcyBvZiB0aGUgd2VicGFnZS4gVG8gc2NyYXBlIHRoZSBkYXRhIGZyb20gdGhlIHdlYnBhZ2UsIHdlIG5lZWQgdG8gZmlyc3QgbGVhcm4gYSBsaXR0bGUgYml0IGFib3V0IHRoZSBjb21wb25lbnRzIHRoYXQgbWFrZSBpdCB0aGUgd2ViIHBhZ2UgaXQgaXMuIAoKSG92ZXJpbmcgb3VyIG1vdXNlIG92ZXIgdGhlIGVsZW1lbnRzIG9mIHRoZSB3ZWJwYWdlIGhpZ2hsaWdodHMgdGhlIHJlc3BlY3RpdmUgc2VjdGlvbiBvZiB0aGUgd2VicGFnZSBpdCByZXByZXNlbnRzLiBCeSBob3ZlcmluZyBvdmVyIHNldmVyYWwgZWxlbWVudHPigJRhbmQgY2xpY2tpbmcgb24gdGhlIGVsZW1lbnRzIG9uIHRoZSByaWdodCBzaWRlIG9mIHRoZSBzY3JlZW7igJR3ZSBjYW4gaW5kZW50aWZ5IHRoZSBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIGRhdGEgd2UgYXJlIGxvb2tpbmcgZm9yLiBBbm90aGVyIG9wdGlvbiBmb3IgaWRlbnRpZnlpbmcgeHBhdGhzIGlzIHRvIHVzZSB0aGUgW3NlbGVjdG9yZ2FkZ2V0IHRvb2xdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ydmVzdC92aWduZXR0ZXMvc2VsZWN0b3JnYWRnZXQuaHRtbCkuICAKCmBgYHtyLHN0ZXAzLCBlY2hvPUZBTFNFfQpzdGVwMyAKYGBgCgpSaWdodCBjbGljayBvbiB0aGUgZWxlbWVudCBhbmQgY29weSB0aGUgWFBhdGguIFdlIHdpbGwgbmVlZCB0aGlzIFhQYXRoIGZvciB0aGUgbmV4dCBzdGVwLgoKYGBge3IsIHN0ZXA0LCBlY2hvPUZBTFNFfQpzdGVwNApgYGAKCk5vdyB3ZSBjYW4gcmV0dXJuIHRvIHRoZSBgUmAgcHJvZ3JhbW1pbmcgZW52aXJvbm1lbnQuCgpgYGB7ciwgc3RlcDUsIGVjaG89RkFMU0V9CnN0ZXA1CmBgYAoKKioqCgojIyMgMikgU2F2ZSB3ZWJwYWdlIGVsZW1lbnQgdG8gYW4gb2JqZWN0IGluIFIgCgpGb3IgdGhlIGZpcnN0IHRhYmxlIHdlIHdhbnQgdG8gc2NyYXBlLCB0aGUgWFBhdGggaXMgYC9odG1sL2JvZHkvZGl2WzRdL2RpdlsxXS90YWJsZWAuIFdlIHVzZSB0aGlzIFhwYXRoIHdpdGggZnVuY3Rpb25zIGZyb20gdGhlIGBydmVzdGAgcGFja2FnZSB0byBzY3JhcGUgdGhlIGRhdGEgZnJvbSB0aGlzIHRhYmxlLgoKCmBgYHtyLHN0ZXA1X3pvb20sIGVjaG89RkFMU0V9CnN0ZXA1X3pvb20KYGBgCgoKTGV0J3MgZXhwbG9yZSB0aGlzIHN0ZXAgaW4gZ3JlYXRlciBkZXRhaWw6CgpXZSBuZWVkIHRvOgoKKyBpbXBvcnQgaHRtbCBjb2RlIGZvciB0aGUgd2VicGFnZQorIGV4dHJhY3QgcGllY2VzICh0YWJsZSkgb3V0IG9mIEhUTUwgZG9jdW1lbnRzICh3ZWJwYWdlKSB1c2luZyBYcGF0aAorIHBhcnNlIHRoZSBodG1sIHRhYmxlIGludG8gYSBkYXRhIGZyYW1lCgpUbyBkbyB0aGlzOgoKKyBXZSBpbXBvcnQgdGhlIGh0bWwgY29kZSB1c2luZyB0aGUgYHJlYWRfaHRtbCgpYCBmdW5jdGlvbiBvZiB0aGUgYHJ2ZXN0YCBwYWNrYWdlCisgV2UgZXh0cmFjdCBzcGVjaWZpYyBjb21wb25lbnRzIG9mIHRoZSB3ZWJwYWdlIHVzaW5nIHRoZSBgaHRtbF9ub2RlcygpYCBmdW5jdGlvbiBvZiB0aGUgYHJ2ZXN0YCBwYWNrYWdlCisgV2UgY29udmVydCB0aGlzIGh0bWwgdGFibGUgaW50byBhIGRhdGFmcmFtZSB1c2luZyB0aGUgYGh0bWxfdGFibGUoKWBmdW5jdGlvbiBvZiB0aGUgYHJ2ZXN0YCBwYWNrYWdlCgoqKlRoZSBgcnZlc3RgIHBhY2thZ2UgcHJvdmlkZXMgd3JhcHBlcnMgZm9yIHRoZSBgeG1sMmAgYW5kIGBodHRyYCBwYWNrYWdlcywgdGh1cyB3ZSBjYW4ganVzdCBpbnN0YWxsIGFuZCBsb2FkIHRoZSBgcnZlc3RgIHBhY2thZ2UgYW5kIGl0IHdpbGwgaW5zdGFsbCBhbmQgbG9hZCBkZXBlbmRlbmN5IHBhY2thZ2VzIGxpa2UgYHhtbDJgIGFuZCBgaHR0cmAgYW5kIGFsbG93IHVzIHRvIHVzZSBmdW5jdGlvbnMgZnJvbSAgYm90aCBvZiB0aGVzZSBwYWNrYWdlcy4qKgoKSW4gZmFjdCwgd2hlbiB3ZSBsb2FkIGBydmVzdGAgdGhlIGZpcnN0IHRpbWUgd2Ugc2VlOgoKYGBge3IsIG91dC53aWR0aD0gIjYwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJydmVzdC5wbmciKSkKYGBgCgpJbiB0aGlzIGNhc2UsIHdlIGFyZSBzY3JhcGluZyB0YWJsZSAxMS4xYSBmcm9tIHRoZSB3ZWJzaXRlLiBGaXJzdCB3ZSBhc3NpZ24gdGhlIHVybCB0byBhIGNoYXJhY3RlciBzdHJpbmcgdG8gdXNlIHdpdGhpbiB0aGUgYHJlYWRfaHRtbCgpYCBmdW5jdGlvbiBvZiB0aGUgYHhtbDJgIHBhY2thZ2UuIAoKYGBge3J9Ck5TRFVIX3VybCA8LSAiaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi9kYXRhL3NpdGVzL2RlZmF1bHQvZmlsZXMvY2Joc3EtcmVwb3J0cy9OU0RVSERldGFpbGVkVGFiczIwMThSMi9OU0RVSERldFRhYnNTZWN0MTFwZTIwMTguaHRtIgpgYGAKCk9uZSBjb3VsZCBhbHNvIGRpcmVjdGx5IHVzZSB0aGUgdXJsIGJ1dCB0aGlzIGlzIGxlc3MgY29udmVuaWVudCBmb3IgcGlwaW5nLiAgCgo8ZGV0YWlscz4gPHN1bW1hcnk+Q2xpY2sgaGVyZSBpZiB5b3UgYXJlIHVuZmFtaWxpYXIgd2l0aCBwaXBpbmcgaW4gUiwgd2hpY2ggdXNlcyB0aGlzIGAlPiVgIG9wcGVyYXRvcjwvc3VtbWFyeT4gIAoKQnkgW3BpcGluZ10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hZ3JpdHRyL3ZpZ25ldHRlcy9tYWdyaXR0ci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHdlIG1lYW4gdXNpbmcgdGhlIGAlPiVgIHBpcGUgb3BlcmF0b3Igd2hpY2ggYXJlIHVzYWJsZSB3aGVuIGxvYWRpbmcgdGhlIHRpZHl2ZXJzZSBvciBzZXZlcmFsIG9mIHRoZSBwYWNrYWdlcyB3aXRoaW4gdGhlIHRpZHl2ZXJzZSBsaWtlIGBkcGx5cmAgYmVjdWFzZSB0aGV5IGxvYWQgdGhlIFtgbWFncml0dHJgIHBhY2thZ2VdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYWdyaXR0ci92aWduZXR0ZXMvbWFncml0dHIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifS4gVGhpcyBhbGxvd3MgdXMgdG8gcGVyZm9ybSBtdWx0aXBsZSBzZXF1ZW50aWFsIHN0ZXBzIG9uIG9uZSBkYXRhIGlucHV0LiAgIAoKPC9kZXRhaWxzPiAgCgogIApUaGUgYHJlYWRfaHRtbCgpYCBmdW5jdGlvbiB0aGVuIGFsbG93cyB1cyB0byBzYXZlIHRoZSBodG1sIGRvY3VtZW50IGZvciB0aGUgd2VicGFnZSBpbnNpZGUgUi4gCgpgYGB7cn0Kd2VicGFnZSA8LSBOU0RVSF91cmwgJT4lCiAgeG1sMjo6cmVhZF9odG1sKCkgCndlYnBhZ2UKYGBgCgpUaGVuIHdlIHVzZSB0aGUgYGh0bWxfbm9kZXMoKWAgZnVuY3Rpb24gb2YgdGhlIGBydmVzdGAgcGFja2FnZSB0byBzZWxlY3QganVzdCB0aGUgdGFibGUxMS4xYSBlbGVtZW50IG9mIHRoZSB3ZWJwYWdlLgoKU2VlIHRoaXMgW3R1dG9yaWFsXShodHRwOi8vZmx1a2VvdXQuZ2l0aHViLmlvLyMpe3RhcmdldD0iX2JsYW5rIn0gKGFuZCB0aGUgW2Fuc3dlcnNdKGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL2NocmlzbWFuL2ZjYjBhODg0NTljZDk4MjM5ZGJlNmQyZDIwMGIwMmQxKXt0YXJnZXQ9Il9ibGFuayJ9IGluIGNhc2UgeW91IGdldCBzdHVjaykgb24gQ1NTIHNlbGVjdG9ycyB0byB1bmRlcnN0YW5kIG1vcmUgYWJvdXQgaG93IHRoaXMgZnVuY3Rpb24gd29ya3MgdG8gdXNlIHRoZSBgeHBhdGhgIHRvIHNlbGVjdCB0aGUgZWxlbWVudHMgb2YgaW50ZXJlc3QgZnJvbSB0aGUgd2VicGFnZS4KCgpgYGB7cn0Kd2VicGFnZV9lbGVtZW50IDwtd2VicGFnZSAlPiUKICBydmVzdDo6aHRtbF9ub2Rlcyh4cGF0aD0nL2h0bWwvYm9keS9kaXZbNF0vZGl2WzFdL3RhYmxlJykKd2VicGFnZV9lbGVtZW50IAoKYGBgCgpGaW5hbGx5LCB0aGUgYGh0bWxfdGFibGUoKWAgZnVuY3Rpb24gb2YgdGhlIGBydmVzdGAgcGFja2FnZSBwYXJzZXMgdGhlIGh0bWwgb2JqZWN0IGludG8gYSBkYXRhIGZyYW1lLgoKYGBge3J9CmxpYnJhcnkoZHBseXIpCnRhYmxlMTEuMWE8LXdlYnBhZ2VfZWxlbWVudCU+JQogIHJ2ZXN0OjpodG1sX3RhYmxlKCkKcHJpbnQodGFibGUxMS4xYSwgbWF4ID0gMikKZ2xpbXBzZSh0YWJsZTExLjFhKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGUgb3V0cHV0IGlzIGEgbGlzdCB3aXRoIG9uZSBlbGVtZW50LCB0byBleHRyYWN0IHRoZSBkYXRhIGZyb20gdGhlIGxpc3Qgd2Ugd2lsbCB1c2UgYnJhY2tldHMgYFtbXV1gIHRvIHNlbGVjdCB0aGUgZmlyc3QgZWxlbWVudCBvZiB0aGUgbGlzdC4KYGBge3J9CnRhYmxlMTEuMWEgPC0gdGFibGUxMS4xYVtbMV1dCmBgYAoKClB1dHRpbmcgdGhpcyBhbGwgb2YgdGhpcyB0b2dldGhlciB3ZSBjYW4gZG8gdGhlIGVudGlyZSBwb3JjZXNzIGxpa2UgdGhpcyB3aXRoIG91ciBwaXBlIG9wcGVyYXRvciBgJT4lYC4KCmBgYHtyfQpOU0RVSF91cmwgPC0gImh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL2NiaHNxLXJlcG9ydHMvTlNEVUhEZXRhaWxlZFRhYnMyMDE4UjIvTlNEVUhEZXRUYWJzU2VjdDExcGUyMDE4Lmh0bSIKdGFibGUxMS4xYSA8LSBOU0RVSF91cmwgJT4lCiAgeG1sMjo6cmVhZF9odG1sKCkgJT4lCiAgcnZlc3Q6Omh0bWxfbm9kZXMoeHBhdGg9Jy9odG1sL2JvZHkvZGl2WzRdL2RpdlsxXS90YWJsZScpICU+JQogIHJ2ZXN0OjpodG1sX3RhYmxlKCkKdGFibGUxMS4xYSA8LSB0YWJsZTExLjFhW1sxXV0KYGBgCgoKTm93IG5lZWQgdG8gcmVwZWF0IHRoZSBhYm92ZSBwcm9jZXNzIGZvciB0aGUgb3RoZXIgdGFibGVzIHdlIGFyZSBpbnRlcmVzdGVkIGluLiAKCiMjIyBXcml0aW5nIGEgZnVuY3Rpb24gdG8gc2NyYXBlIG11bHRpcGxlIHRhYmxlcwoKV2UgY2FuIGNyZWF0ZSBhIGZ1bmN0aW9uIHRvIGFjY29tcGxpc2ggdGhpcyBzdWNjaW5jdGx5LiAKRnVuY3Rpb25zIGFsbG93IHVzIHRvIHBlcmZvcm0gdGhlIHNhbWUgcHJvY2VzcyBvbiBtdWx0aXBsZSBkYXRhIGlucHV0cy4gU2VlIFt0aGlzIG90aGVyIGNhc2Ugc3R1ZHldKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9vY3MtYmxvb21iZXJnLXZhcGluZy1jYXNlLXN0dWR5Lyl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9yZSBkZXRhaWxzIGFib3V0IGhvdyB0byB3cml0ZSBhIGZ1bmN0aW9uLgoKSW4gZ2VuZXJhbCwgdGhlIHByb2Nlc3MgcGYgd3JpdGluZyBmdW5jdGlvbnMgaW52b2x2ZXMgZmlyc3Qgc3BlY2lmeWluZyBhbiBpbnB1dCB0aGF0IGlzIHVzZWQgd2l0aGluIHRoZSBmdW5jdGlvbiB0byBjcmVhdGUgYW4gb3V0cHV0LiBJbiB0aGlzIGNhc2UgdGhlIGRhdGEgaW5wdXQgaXMgYFhQQVRIYCB3aGljaCB3aWxsIGJlIHJlcGxhY2VkIGJ5IGFuIGFjdHVhbCB4cGF0aCBhbmQgdGhlIG51c2VkIGluIHRoZSBzdWJzZXF1ZW50IHN0ZXBzIHRvIHNjcmFwZSB0aGUgZGF0YSBmcm9tIGVhY2ggdGFibGUgdGhhdCBhbiB4cGF0aCBpcyBzdXBwbGllZCBmb3IuCgpXZSB3aWxsIGFsbCB0aGlzIGZ1bmN0aW9uIGBzY2FycGVyYC4KCmBgYHtyfQpzY3JhcGVyIDwtIGZ1bmN0aW9uKFhQQVRIKXsKICBOU0RVSF91cmwgPC0gImh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL2NiaHNxLXJlcG9ydHMvTlNEVUhEZXRhaWxlZFRhYnMyMDE4UjIvTlNEVUhEZXRUYWJzU2VjdDExcGUyMDE4Lmh0bSIKICB0YWJsZSA8LSBOU0RVSF91cmwgJT4lCiAgcmVhZF9odG1sKCkgJT4lCiAgaHRtbF9ub2Rlcyh4cGF0aD1YUEFUSCkgJT4lCiAgaHRtbF90YWJsZSgpCiAgb3V0cHV0IDwtIHRhYmxlW1sxXV0KICBvdXRwdXQKfQpgYGAKCk5vdyB3ZSBjYW4gYXBwbHkgdGhlIGZ1bmN0aW9uIHdlIGNyZWF0ZWQgdG8gZWFjaCBvZiB0aGUgeHBhdGhzIGZvciBlYWNoIG9mIHRoZSB0YWJsZXMgb24gdGhlIHdlYnNpdGUgdGhhdCB3ZSB3b3VsZCBsaWtlIHRvIHVzZSBpbiBvdXIgZGF0YSBhbmFseXNpcy4KCmBgYHtyfQp0YWJsZTExLjFiIDwtIHNjcmFwZXIoWFBBVEggPSAiL2h0bWwvYm9keS9kaXZbNF0vZGl2WzJdL3RhYmxlIikKdGFibGUxMS4yYSA8LSBzY3JhcGVyKFhQQVRIID0gJy9odG1sL2JvZHkvZGl2WzRdL2RpdlszXS90YWJsZScpCnRhYmxlMTEuMmIgPC0gc2NyYXBlcihYUEFUSCA9ICcvaHRtbC9ib2R5L2Rpdls0XS9kaXZbNF0vdGFibGUnKQp0YWJsZTExLjNhIDwtIHNjcmFwZXIoWFBBVEggPSAnL2h0bWwvYm9keS9kaXZbNF0vZGl2WzVdL3RhYmxlJykKdGFibGUxMS4zYiA8LSBzY3JhcGVyKFhQQVRIID0gJy9odG1sL2JvZHkvZGl2WzRdL2Rpdls2XS90YWJsZScpCnRhYmxlMTEuNGEgPC0gc2NyYXBlcihYUEFUSCA9ICcvaHRtbC9ib2R5L2Rpdls0XS9kaXZbN10vdGFibGUnKQp0YWJsZTExLjRiIDwtIHNjcmFwZXIoWFBBVEggPSAnL2h0bWwvYm9keS9kaXZbNF0vZGl2WzhdL3RhYmxlJykKYGBgCgoKR3JlYXQhIFdlIGhhdmUgc3VjY2Vzc2Z1bGx5IHNjcmFwZWQgdGhlIGRhdGEuCgpOb3cgd2UgbmVlZCB0byB3cmFuZ2xlIHRoZSBkYXRhLgoKCiMjICoqRGF0YSBFeHBsb3JhdGlvbiBhbmQgV3JhbmdsaW5nKioKKioqIAoKTm93IHRoYXQgd2UndmUgaW1wb3J0ZWQgdGhlIGRhdGEsIGxldCdzIHNlZSBpZiB3ZSBjYW4gd3JhbmdsZSBhIHRhYmxlLiBTaW5jZSB0aGUgZGF0YSBhcHBlYXJzIHRvIGJlIGZvcm1hdGVkIGluIGEgc2ltaWxhciB3YXkgaW4gZWFjaCBvZiB0aGUgdGFibGVzLCBpdCBpcyBsaWtlbHkgdGhhdCB3aGF0ZXZlciBzdGVwcyB3ZSB0YWtlIHRvIHdyYW5nbGUgdGhpcyBmaXJzdCB0YWJsZSB3aWxsIGFsc28gYmUgbmVjZXNzYXJ5IGluIHRoZSB3cmFuZ2xpbmcgb2Ygc3Vic2VxdWVudCB0YWJsZXMuIFRoaXMgaXMgYmVjYXVzZSB3ZWxsLW1haW50YWluZWQgZGF0YSBzb3VyY2VzIG9mdGVuIGZvcm1hdCBkaWZmZXJlbnQgZGF0YXNldHMgc2ltaWxhcmx5LiBXZSBjYW4gdGFrZSBhZHZhbnRhZ2Ugb2YgdGhpcyBzaW1pbGFyaXR5IHRvIHNwZWVkIHVwIHRoZSB3cmFuZ2xpbmcgcHJvY2Vzcy4gCgoqKlRhYmxlMTEuMWEqKgoKRmlyc3Qgd2Ugd2FudCB0byByZW1vdmUgdGhlIGxhc3Qgcm93IG9mIG91ciBkYXRhIGZyYW1lLCB3aGljaCBoYXBwZW5zIHRvIGJlIHRoZSBsZWdlbmQgb2Ygb3VyIHRhYmxlLiBSZWNhbGwgZnJvbSBsb29raW5nIGF0IHRoZSB3ZWJzaXRlIHRoYXQgdGhlcmUgaXMgYSBsZWdlbmQgZm9yIHRoaXMgdGFibGUuCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAidGFibGUxMS4xYS5wbmciKSkKYGBgCgpXZSBjYW4gdGFrZSBhIGxvb2sgYXQgdGhlIGxhc3Qgcm93IHVzaW5nIHRoZSBgdGFpbGAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gV2UgY2FuIHNwZWNpZnkgdGhhdCB3ZSBvbmx5IHdhbnQgdG8gc2VlIHRoZSBsYXN0IHJvdyBieSB1c2luZyB0aGUgYG4gPSAxYCBhcmd1bWVudC4KCmBgYHtyfQp0YWJsZTExLjFhICU+JQogIGRwbHlyOjphc190aWJibGUoKSAlPiUKICB0YWlsKG4gPSAxKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB0aGUgbGVnZW5kIGlzIHJlcGVhdGVkIGZvciBldmVyeSBjb2x1bW4uIExldCdzIHRha2UgYSBsb29rIGF0IHRoZSB5ZWFyIDIwMDQgY29sdW1uLgpgYGB7cn0KdGFibGUxMS4xYSAlPiUKICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lICAKICBzZWxlY3QoYDIwMDRgKSAlPiUKICB0YWlsKG4gPSAxKQpgYGAKCkxldCdzIHNhdmUgdGhpcyBzbyB0aGF0IHdlIGNhbiByZWZlciBiYWNrIHRvIGl0IGxhdGVyOgpgYGB7cn0KbGVnZW5kIDwtIHRhYmxlMTEuMWEgJT4lCiAgYXNfdGliYmxlKCkgJT4lICAKICBzZWxlY3QoYDIwMDRgKSAlPiUKICB0YWlsKG4gPSAxKQpgYGAKCkFub3RoZXIgd2F5IHRvIGxvb2sgYXQgdGhlIGxhc3Qgcm93IGlzIHRvIHVzZSB0aGUgYG4oKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgdXNlZCBpbnNpZGUgb3RoZXIgYGRwbHlyYCBmdW5jdGlvbnMgYW5kIGl0IGNvdW50cyB0aGUgdG90YWwgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBvZiBhIGdyb3VwLiBXaXRoaW4gdGhlIFtgc2xpY2UoKWAgZnVuY3Rpb25dKGh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2Uvc2xpY2UuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBvZiB0aGUgYGRwbHlyYCBwYWNrZ2UsIGl0IGFsbG93cyB5b3UgdG8gcmVmZXIgdGhlIGZ1bGwgbGVuZ3RoIG9mIHRoZSBvYmplY3QuCgpgYGB7cn0KdGFibGUxMS4xYSAlPiUKICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lCiAgc2xpY2UobigpKSAKYGBgCldlIGNhbiB1c2UgdGhlIGBzbGljZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIHRvIHJlbW92ZSB0aGlzIHJvdywgYnkgdXNpbmcgdGhlIGBzbGljZWBmdW5jdGlvbiB0byBzZWxlY3QgZnJvbSB0aGUgZmlyc3Qgcm93IHVzaW5nIGAxOmAgdG8gdGhlIHNlY29uZCB0byBsYXN0IHJvdyB1c2luZyBgbigpLTFgLgoKV2UgYXJlIGFsc28gZ29pbmcgdG8gdXNlIGEgc3BlY2lhbCBwaXBlIG9wcGVyYXRvciBmcm9tIHRoZSBbYG1hZ3JpdHRyYCBwYWNrYWdlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbWFncml0dHIvdmlnbmV0dGVzL21hZ3JpdHRyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gY2FsbGVkIHRoZSBjb21wb3VuZCBhc3NpZ25tZW50IHBpcGUtb3BlcmF0b3Igb3Igc29tZXRpbWVzIHRoZSBkb3VibGUgcGlwZSBvcGVyYXRvci4gVGhpcyBhbGxvd3MgdXMgdG8gdXNlIHRoZSB0YWJsZTExLjFhIGFzIG91ciBpbnB1dCBhbmQgcmVhc2lnbiBpdCBhdCB0aGUgZW5kIGFmdGVyIGFsbCB0aGUgc3RlcHMgaGF2ZSBiZWVuIHBlcmZvcm1lZC4KCmBgYHtyfQpsaWJyYXJ5KG1hZ3JpdHRyKQp0YWJsZTExLjFhICU8PiUKICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lCiAgc2xpY2UoMToobigpLTEpKQpgYGAKCk5vdyBsZXQncyB0YWtlIGEgbG9vayBhdCBkYXRhOgpgYGB7cn0KdGFibGUxMS4xYQpgYGAKCkdyZWF0ISBXZSBjYW4gc2VlIHRoZSB0aGUgbGVnZW5kIGlzIG5vIGxvbmdlciBwYXJ0IG9mIHRoZSBkYXRhLgoKTm93IGxldCdzIHVzZSB0aGUgbGVnZW5kIHRvIHJlY29kZSB0aGUgZGF0YS4gVGhlcmUgYXJlIG1hbnkgZGlmZmVyZW50IHZhbHVlcyBmb3IgbWlzc2luZyBkYXRhLCB0aGF0IHdlIHdvdWxkIGxpa2UgdG8gcmVwbGFjZSB3aXRoIGBOQWAgaW5zdGVhZC4KV2UgY2FuIHVzZSB0aGUgYHB1bGwoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byB0YWtlIGEgbG9vayBhdCB0aGUgbGVnZW5kIGRhdGE6CgpgYGB7cn0KcHVsbChsZWdlbmQsIGAyMDA0YCkKYGBgCgpMb29rcyBsaWtlIHdlIHdhbnQgdG8gcmVwbGFjZSB2YWx1ZXMgdGhhdCBhcmU6IGAqYCwgYC0tYCwgYGRhYCwgYG5jYCwgYW5kIGBucmAuIFdlIGNhbiB1c2UgdGhlIGBuYV9pZigpYCBmdW5jdGlvbiB0byByZWNvZGUgdGhlc2UgdmFsdWVzIHRvIGBOQWAuCgphdm9jYWRvLi4uIHRoZXJlIGlzbnQgc3VwcG9ydCBmb3IgZG9pbmcgdGhpcyBpbiBvbmUgY29tbWFuZC4uLiBidXQgY291bGQgYXQgbGVhc3QgZG8gdHdvIGNvbW1hbmRzCgpgYGB7cn0KdGFibGUxMS4xYSAlPD4lCiAgZHBseXI6Om5hX2lmKCJuYyIpICU+JQogIGRwbHlyOjpuYV9pZigiLS0iKSAlPiUKICBkcGx5cjo6bmFfaWYoIiIpICU+JQogIGRwbHlyOjpuYV9pZigiKiIpCgp0YWJsZTExLjFhIApgYGAKCk5vdyBsZXQncyByZW5hbWUgdGhlIGZpcnN0IGNvbHVtbiB1c2luZyB0aGUgYHJlbmFtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiBUaGlzIHJlcXVpcmVzIGxpc3RpbmcgdGhlIG5ldyBuYW1lIGZpcnN0IGxpa2Ugc286IGBuZXdfbmFtZSA9IG9sZF9uYW1lYC4KYGBge3J9CnRhYmxlMTEuMWEgJTw+JQogIGRwbHlyOjpyZW5hbWUoTUhTX3NldHRpbmcgPSAKICAgICAgICAgICAgICAgICAgYFNldHRpbmcgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlV2FzIFJlY2VpdmVkYCkKaGVhZCh0YWJsZTExLjFhKQpgYGAKCk5pY2UhCgpOb3cgeW91IG1heSBub3RpY2UgdGhhdCB0aGUgaW5kaXZpZHVhbCB2YWx1ZXMgaGF2ZSBhbiBgImEiYCBhZnRlciB0aGUgbnVtZXJpYyB2YWx1ZS4KCkFjY29yZGluZyB0byB0aGUgbGVnZW5kIHRoaXMgaW5kaWNhdGVzIGlmICJ0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoaXMgZXN0aW1hdGUgYW5kIHRoZSAyMDE4IGVzdGltYXRlIGlzIHNpZ25pZmljYW50IGF0IHRoZSAuMDUgbGV2ZWwuIgoKV2hpbGUgdGhpcyBpcyB1c2VmdWwgaW5mb3JtYXRpb24sIGl0IG1ha2VzIGl0IGRpZmZpY3VsdCB0byB3b3JrIHdpdGggb3VyIG51bWVyaWMgdmFsdWVzLCBzbyB3ZSB3YW50IHRvIHJlbW92ZSB0aGVtLgoKU2luY2UgbG93ZXIgY2FzZSAiYSIgdmFsdWVzIG9jY3VyIGluIHRoZSBmaXJzdCBjb2x1bW4gdmFsdWVzLCB3ZSB3YW50IHRvIG1ha2VzIHN1cmUgd2UgZG9udCByZW1vdmUgdGhlc2UuCgpTbyBob3cgY2FuIHdlIGRvIHRoaXM/IFdlIGNhbiB1c2UgdGhlIGBzdHJpbmdyYCBwYWNrYWdlIHRvIG1vZGlmeSBjaGFyYWN0ZXIgc3RyaW5ncy4gYW5kIHdlIGNhbiB1c2UgdGhlIGBkcGx5cmAgZnVuY3Rpb25zIGBtdXRhdGUoKWAsIGBzZWxlY3QoKWAgYW5kIGBhY3Jvc3MoKWAgdG8gc3BlY2lmeSB3YW50IGNvbHVtbnMgd2Ugd2FudCB0byBjaGFuZ2UuCgpDdXJyZW50bHkgYWxsIG9mIG91ciBkYXRhIGlzIG9mIGNsYXNzIGNoYXJhY3RlciBhcyBpbmRpY2F0ZWQgYnkgdGhlIGA8Y2hyPmAgdW5kZXIgdGhlIGNvbHVtbiBuYW1lcy4gCgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgZm9yIGFuIGV4cGxhbmF0aW9uIG9mIHdoYXQgYSBjaGFyYWN0ZXIgc3RyaW5nIGlzIDwvc3VtbWFyeT4KClRoZXJlIGFyZSBzZXZlcmFsIGNsYXNzZXMgb2YgZGF0YSBpbiBSIHByb2dyYW1taW5nLiBDaGFyYWN0ZXIgaXMgb25lIG9mIHRoZXNlIGNsYXNzZXMuIApBIGNoYWN0ZXIgc3RyaW5nIGlzIGFuIGluZGl2aWR1YWwgZGF0YSB2YWx1ZSBtYWRlIHVwIG9mIGNoYXJhY3RlcnMuIFRoaXMgY2FuIGJlIGEgcGFyYWdyYXBoLCBsaWtlIHRoZSBsZWdlbmQgZm9yIHRoZSB0YWJsZSwgb3IgaXQgY2FuIGJlIGEgc2luZ2xlIGxldHRlciBvciBudW1iZXIgbGlrZSB0aGUgbGV0dGVyIGAiYSJgIG9yIHRoZSBudW1iZXIgYCIzImAuIElmIGRhdGEgaXMgb2YgY2xhc3MgY2hhcmFjdGVyLCB0aGFuIHRoZSBudW1lcmljIHZhbHVlcyB3aWxsIG5vdCBiZSBwcm9jZXNzZWQgbGlrZSBhIG51bWVyaWMgdmFsdWUgaW4gYSBtYXRoZW1hdGljYWwgc2Vuc2UuIElmIHlvdSB3YW50IHlvdXIgbnVtZXJpYyB2YWx1ZXMgdG8gYmUgaW50ZXJwcmV0ZWQgdGhhdCB3YXksIHRoZXkgbmVlZCB0byBiZSBjb252ZXJ0ZWQgdG8gYSBudW1lcmljIGNsYXNzLiBUaGUgb3B0aW9ucyB0eXBpY2FsbHkgdXNlZCBhcmUgaW50ZWdlciAod2hpY2ggaGFzIG5vIGRlY2ltYWwgcGxhY2UpIGFuZCBkb3VibGUgcHJlY2lzaW9uICh3aGljaCBoYXMgYSBkZWNpbWFsIHBsYWNlKS4gCgo8L2RldGFpbHM+CgogIApUaGUgYHN0cmluZ3JgIHBhY2thZ2UgaGFzIGZ1bmN0aW9ucyB0aGF0IGFsbG93IHVzIHRvIHJlcGxhY2UgKHRoZSBgc3RyX3JlcGxhY2UoKWAgZnVuY3Rpb24pIG9yIHJlbW92ZSh0aGUgYHN0cl9yZW1vdmUoKWAgZnVuY3Rpb24pIGNoYXJhY3RlcnMuIAoKVG8gdXNlIHRoZXNlIHdlIG5lZWQgdG8gYmUgYWJsZSB0byBzcGVjaWZ5IHdoYXQgd2Ugd2FudCB0byByZW1vdmUgYW5kIHJlcGxhY2UuIAoKSGVyZSBpcyBhIHBhcnQgb2YgYSBbY2hlYXRzaGVldF0oaHR0cHM6Ly9yc3R1ZGlvLmNvbS9yZXNvdXJjZXMvY2hlYXRzaGVldHMvKXt0YXJnZXQ9Il9ibGFuayJ9IGFib3V0IHN0cmluZyBtYW5pcHVsYXRpb24gZnJvbSByc3R1ZGlvLgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInJlZ2V4LnBuZyIpKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB3ZSBjYW4gcmVmZXIgdG8gYW55IGRpZ2l0IChzdWNoIGFzIDEsMiwzIGV0Yy4pIGFzIGBbOmRpZ2l0Ol1gLgpXZSBjYW4gYWxzbyBzZWUgdGhhdCB3ZSBjYW4gcmVmZXIgdG8gYW55IHB1bmN0aW9uIG1hcmsgYXMgYFs6cHVuY3Q6XWAuCkZpbmFsbHksIHdlIHNlZSB0aGF0IHNwYWNlcyBhbmQgdGFibHMgY2FuIGJlIHJlZmVyZWQgdG8gYXMgYFs6Ymxhbms6XWAuCgoKSWYgd2UgdGFrZSBhIGNsb3NlciBsb29rIGF0IHRoZSBmaXJzdCBjb2x1bW4gb2Ygb3VyIHRhYmxlICh1c2luZyB0aGUgYHB1bGwoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSksIHdlIGNhbiBzZWUgdGhhdCBiZXNpZGVzIHRoZSBgImEiYCB2YWx1ZXMgdGhhdCB3ZSBzZWUgYWRqYWNlbnQgdG8gb3VyIG51bWVyaWMgdmFsdWVzIGluIHRoZSBib2R5IG9mIHRoZSB0YWJsZSwgd2UgYWxzbyBzb21lIGxhcmdlIHdoaXRlIHNwYWNlcywgc29tZSBudW1lcmljIHZhbHVlcywgaW5zdGFuY2VzIG9mIGBcclxuYCwgYXMgd2VsbCBhcyBzb21lIGNvbW1hcyBhbmQgb3RoZXIgcHVuY3R1YXRpb24gbWFya3MuIAoKYGBge3J9CnB1bGwodGFibGUxMS4xYSwgTUhTX3NldHRpbmcpCmBgYAoKCldlIGNhbiB1c2UgdGhlIGBzdHJfcmVtb3ZlX2FsbCgpYCBmdW5jdGlvbiB3aGljaCBpcyBhIHZhcmlhbnQgb2YgdGhlIGBzdHJfcmVtb3ZlKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZSAod2hpY2ggYWxsb3dzIHVzIHRvIHJlbW92ZSBhbGwgb2NjdXJlbmNlcyBvZiBzZXBjaWZpY2VkIGNoYXJhY3RlcnMgaW4gZWFjaCByb3cgcmF0aGVyIHRoYW4ganVzdCB0aGUgZmlyc3Qgb2NjdXJhbmNlLCB3aGljaCBpcyB3aGF0IGBzdHJfcmVtb3ZlKClgIGRvZXMpLCB0byByZW1vdmUgdGhlIGRpZ2l0IHZhbHVlcywgdGhlIGBcclxuYCBjaGFyYWN0ZXJzIGFuZCB0aGUgcHVuY3Rpb25hdGlvbiBtYXJrcyBmcm9tIHRoZSBjb2x1bW4gY2FsbGVkIGBNSFNfc2V0dGluZ2AuCgpVc2luZyB0aGUgYG11dGF0ZSgpYCBmdW5jdGlvbiB3ZSBzcGVjaWZ5IHRoYXQgd2Ugd2FudCB0byBjaGFuZ2UgdGhpcyBwYXJ0aWN1bGFyIGNvbHVtbiBhbmQgcmVwbGFjZSBpdCB3aXRoIGEgdmVyc2lvbiBvZiB0aGlzIGNvbHVtbiB0aGF0IGhhcyByZW1vdmVkIGNoYXJhY3RlcnMgdGhhdCBtYXRjaCBkaWdpdHMsIGByXG5gIG9yIHB1bmN0aW9uYXRpb24gbWFya3MuCgpXZSBuZWVkIHRvIHNwZWNpZnkgdGhhdCB0aGUgY2hhcmFjdGVyIHN0cmluZ3MgdGhhdCBzaG91bGQgYmUgdXNlZCBjYW4gYmUgZm91bmQgaW5nIHRoZSBgTUhTX3NldHRpbmdgIGNvbHVtbiBieSB1c2luZyB0aGUgYHN0cmluZyA9YCBhcmd1bWVudCBhbmQgdGhlIHBhdHRlcm5zIHRvIGZpbmQgYW5kIHJlbW92ZSBhcmUgc3BlY2lmaWVkIHVzaW5nIHRoZSBgcGF0dGVybiA9YCBhcmd1bWVudC4KClRvIGFsbG93IHVzIHRvIGxvb2sgZm9yIGFsbCB0aHJlZSBvZiB0aGVzZSBwYXR0ZXJucyBhdCB0aGUgc2FtZSB0aW1lLCB3ZSBjYW4gdXNlIHRoZSBgfGAgc3ltYm9sIGJldHdlZW4gZWFjaCBwYXR0ZXJuLgoKYGBge3J9CnRhYmxlMTEuMWEgJTw+JQptdXRhdGUoTUhTX3NldHRpbmcgPSAKICAgICAgICAgc3RyX3JlbW92ZV9hbGwoc3RyaW5nID0gTUhTX3NldHRpbmcsIAogICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiWzpkaWdpdDpdfFxyXG58WzpwdW5jdDpdfCIpKQoKYGBgCgpXZSBhbHNvIHdhbnQgdG8gcmVwbGFjZSB0aGUgc3BhY2VzIHdpdGggYW4gdW5kZXJzY29yZS4gV2UgY2FuIHNlZSB0aGF0IHNvbWV0aW1lcyB0aGVyZSBhcHBlYXJzIHRvIGJlIG1vcmUgdGhhbiBvbmUgc3BhY2UuIFdlIGNhbiBzcGVjaWZ5IHRoYXQgd2Ugd2FudCBhbnkgb2NjdXJhbmNlIG9mIDEgb3IgbW9yZSAgdG8gYmUgcmVwbGFjZWQgYnkgdXNpbmcgdGhlIGB7MSx9YCBub3RhdGlvbi4KClNlZSBoZXJlIGZvciBhbiBleHBsYW5hdGlvbiBvZiB0aGlzIG9uIHRoZSBjaGVhdCBzaGVldDoKCmBgYHtyfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAicXVhbnRpZmllcnMucG5nIikpCmBgYAoKU28gbm93IHdlIHdpbGwgdXNlIHRoZSBgc3RyX3JlcGxhY2VfYWxsKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZS4KSW4gdGhpcyBjYXNlIHdlIGFsc28gbmVlZCB0byBzcGVjaWZ5IGEgcmVwbGFjZW1lbnQgd2l0aCB0aGUgYHJlcGxhY2VtZW50ID0gYCBhcmd1bWVudC4KCmBgYHtyfSAKdGFibGUxMS4xYSU8PiUKbXV0YXRlKE1IU19zZXR0aW5nID0gCiAgICAgICAgIHN0cl9yZXBsYWNlX2FsbChzdHJpbmcgPSBNSFNfc2V0dGluZywKICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJbOmJsYW5rOl17MSx9IiwgCiAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiXyIpKQpgYGAKCk5vdyB0byBmaW5hbGx5IHJlbW92ZSB0aGUgImEiIHZhbHVlcyBhbmQgdGhlIGNvbW1hcyBmcm9tIHRoZSBib2R5IG9mIHRoZSB0YWJsZSB3ZSBjYW4gdXNlIGBzdHJfcmVtb3ZlX2FsbCgpYCBmdW5jdGlvbiB5ZXQgYWdhaW4uIEhvd2V2ZXIgdGhpcyB0aW1lIHRvIHNwZWNpZnkgdGhhdCB3ZSB3YW50IGFsbCBjb2x1bW5zIGV4Y2VwdCB0aGUgZmlyc3QgY29sdW1uIGNhbGxlZCBgTUhTX3NldHRpbmdgLCB3ZSBjYW4gdXNlIHRoZSBgYWNyb3NzKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIFRoaXMgYWxsb3dzIHVzIHRvIHNwZWNpZnkgd2hhdCBjb2x1bW5zIHdlIHdhbnQgdG8gbXV0YXRlIGJ5IHVzaW5nIHRoZSBgLmNvbHMgPSBgIGFyZ3VtZW50LiBXZSBjYW4gc2VsZWN0IGFsbCBjb2x1bW5zIGV4Y2VwdCB0aGUgZmlyc3QgY29sdW1uIGNhbGxlZCBgTUhTX3NldHRpbmdgIGJ5IHVzaW5nIGEgbWludXMgc2lnbiBgLWAgaW4gZnJvbnQgb2YgdGhlIGNvbHVtbiBuYW1lLgoKYGBge3J9CnRhYmxlMTEuMWElPD4lCm11dGF0ZShkcGx5cjo6YWNyb3NzKC5jb2xzID0gLU1IU19zZXR0aW5nLAogICAgICAgICAgICAgICAgc3RyaW5ncjo6c3RyX3JlbW92ZV9hbGwsICJhfCwiKSkKCnRhYmxlMTEuMWEKYGBgCgpPdXIgdGFibGUgaXMgbG9va2luZyBtdWNoIGJldHRlciEKCgpXZSB3b3VsZCBhbHNvIGxpa2UgdG8gcmVtb3ZlIGEgY291cGxlIG9mIHJvd3MgdGhhdCBhcmUgY29tcGxldGVseSBlbXB0eS4gVGhlc2UgYXJlIHRoZSByb3dzIHdoZXJlIHRoZSBmaXJzdCBjb2x1bW4gdmFsdWVzIGFyZSBgR2VuZWFybF9NZWRpY2luZWAgYW5kIGBKdXZlbmlsZV9KdXN0aWNlYC4gSWYgd2UgbG9vayBhdCB0aGUgd2Vic2l0ZSwgd2UgY2FuIHNlZSB0aGF0IHRoZXNlIHdlcmUgbGVhZGluZyBsaW5lIHdpdGggbm8gZGF0YS4KCmBgYHtyfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAidGFibGUxMS4xYS5wbmciKSkKYGBgCgpXZSBjYW4gcmVtb3ZlIHRoZW0gdXNpbmcgdGhlIGBmaWx0ZXIoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gV2UgY2FuIHNwZWNpZnkgdGhhdCB3ZSBkb250IHdhbnQgdG8ga2VlcCB0aGVzZSByb3dzIGJ5IHVzaW5nIHRoZSBgIT1gIG5vdCBlcXVhbCB0byBvcHBlcmF0b3IuIAoKYGBge3J9CnRhYmxlMTEuMWEgJTw+JQogIGRwbHlyOjpmaWx0ZXIoTUhTX3NldHRpbmcgIT0gIkdlbmVyYWxfTWVkaWNpbmUiKSAlPiUKICBkcGx5cjo6ZmlsdGVyKE1IU19zZXR0aW5nICE9ICJKdXZlbmlsZV9KdXN0aWNlIikgCnRhYmxlMTEuMWEgCmBgYAoKCk5vdyB3ZSB3b3VsZCBsaWtlIHRvIGNoYW5nZSB0aGUgc2hhcGUgb2Ygb3VyIHRhYmxlIHNvIHRoYXQgd2UgaGF2ZSBhIG5ldyBjb2x1bW4gdGhhdCByZXBlcmVzZW50cyB0aGUgeWVhciBhbmQgYSBuZXcgY29sdW1uIHRoYXQgcmVwcmVzZW50cyB0aGUgdmFsdWUgZm9yIHRoYXQgeWVhci4gVG8gZG8gc28gd2Ugd2lsbCBiZSBtYWtpbmcgb3VyIHRhYmxlICJsb25nZXIiLCBtZWFuaW5nIHRoYXQgaXQgd2lsbCBoYXZlIGZld2VyIHJvd3MgYW5kIG1vcmUgY29sdW1ucy4gIFNlZSBbaGVyZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV2lkZV9hbmRfbmFycm93X2RhdGEpIGZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IGRpZmZlcmVudCB0YWJsZSBmb3JtYXRzLCB0eXBpY2FsbHkgcmVmcmVlZCB0byBhcyB3aWRlIGFuZCBsb25nIG9yIHNvbWV0aW1lcyBuYXJyb3cuCgpXZSB3aWxsIHVzZSB0aGUgYHBpdm90X2xvbmdlcigpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlIHRvIGNoYW5nZSB0aGUgc2hhcGUgb2Ygb3VyIHRhYmxlLiAKClRoZXJlIGFyZSAzIG1haW4gYXJndW1lbnRzIGluIHRoaXMgZnVuY3Rpb246ICAgCjEpIGNvbHMgLSB3aGljaCBzcGVjaWZpZXMgd2hhdCBjb2x1bW5zIHRvIGNvbGxhcHNlICAKMikgbmFtZXNfdG8gLSB3aGljaCBzcGVjaWZpZXMgdGhlIG5hbWUgb2YgdGhlIG5ldyBjb2x1bW4gdGhhdCB3aWxsIGJlIGNyZWF0ZWQgdGhhdCB3aWxsIGNvbnRhaW4gdGhlIGNvbHVtbiBuYW1lcyBvZiB0aGUgY29sdW1ucyB5b3UgYXJlIGNvbGxhcHNpbmcgIAozKSB2YWx1ZXNfdG8gLSB3aGljaCBzcGVjaWZpZXMgdGhlIG5hbWUgb2YgdGhlIG5ldyBjb2x1bW4gdGhhdCB3aWxsIGJlIGNyZWF0ZWQgdGhhdCB3aWxsIGNvbnRhaW4gdGhlIHZhbHVlcyBmcm9tIHRoZSBjb2x1bW5zIHlvdSBhcmUgY29sbGFwc2luZyAKClRvIHNwZWNpZnkgdGhhdCB3ZSB3YW50IHRvIGNvbGxhcHNlIGFsbCBjb2x1bW5zIGV4Y2VwdCB0aGUgYE1IU19zZXR0aW5nYCBjb2x1bW4gd2UgY2FuIGFnYWluIHVzZSB0aGUgbWludXMgc2lnbi4KCmBgYHtyfQpsaWJyYXJ5KHRpZHlyKQp0YWJsZTExLjFhICU8PiUKICB0aWR5cjo6cGl2b3RfbG9uZ2VyKGNvbHMgPSAtIE1IU19zZXR0aW5nLCAKICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiWWVhciIsCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIk51bWJlciIpCnRhYmxlMTEuMWEKYGBgCgpXZSBjYW4gc2VlIHRoYXQgb3VyIHRhYmxlIGlzIG5vdyBtdWNoIGxvbmdlci0gYXMgd2UgaGF2ZSAzNDAgcm93cyEKCiMjIyMgey5xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpXaHkgZG8gd2UgaGF2ZSAzNDAgcm93cyBub3c/CgojIyMjCgoKCkZpbmFsbHksIHdlIGFsc28gd2FudCB0byBjaGFuZ2Ugb3VyIHZhbHVlcyB0byBiZSBudW1lcmljIGFzIG9wcG9zZWQgdG8gY2hhcmFjdGVyIHNvIHRoYXQgd2UgY2FuIHVzZSB0aGVtIGluIG1hdGhlbWF0aWNhbCBmdW5jdGlvbnMuIFdlIGNhbiB1c2UgdGhlIGJhc2UgYGFzLm51bWVyaWMoKWAgZnVuY3Rpb24uIEFnYWluIHdlIHdpbGwgdXNlIHRoZSBgYWNyb3NzKClgIGZ1bmN0aW9uIHRvIGluZGljYXRlIHdoYXQgdmFyYWlibGVzIHdlIHdpc2ggdG8gbXV0YXRlLgoKYGBge3J9CnRhYmxlMTEuMWEgJTw+JQogIG11dGF0ZShhY3Jvc3MoLmNvbHMgPWMoWWVhciwgTnVtYmVyKSwgYXMubnVtZXJpYykpCgp0YWJsZTExLjFhCmBgYAoKTm93IHdlIHNlZSB0aGF0IHRoZSBgWWVhcmAgYW5kIGBOdW1iZXJgIHZhcmlhYmxlcyBhcmUgb2YgY2xhc3MgZG91YmxlIGJlY2F1c2Ugb2YgdGhlIGA8ZGJsPmAgdW5kZXIgdGhlIGNvbHVtbiBuYW1lLgoKCk5vdyB3ZSB3YW50IHRvIHdyYW5nbGUgYWxsIG9mIG91ciBvdGhlciB0YWJsZXMgd2hpY2ggYXJlIGZvcm1hdHRlZCBzaW1pbGFybHkuCgpXZSBjYW4gYWdhaW4gd3JpdGUgYSBmdW5jdGlvbiB0byBzaW1wbGlmeSB0aGlzIHByb2Nlc3MuCgpUaGUgZnVuY3Rpb24gbmVlZHMgdG86CgotIHJlbW92ZSB0aGUgbGFzdCByb3cgb2YgdGhlIHRhYmxlCi0gZ2V0IHJpZCBvZiBjZXJ0YWluIHBhdHRlcm5zCi0gdHJhbnNpdGlvbiB0aGUgZGF0YSB0byBsb25nIGZvcm1hdAoKYGBge3J9CmRhdGFfcHJlcF9zZXR0aW5ncyA8LSBmdW5jdGlvbihUQUJMRSwgb2xkX2NvbCwgbmV3X2NvbCwgcGl2b3RfY29sKXsKICBUQUJMRSA8LSBUQUJMRVstZGltKFRBQkxFKVsxXSxdCiAgVEFCTEUgPC0gVEFCTEUgJT4lCiAgbmFfaWYoIm5jIikgJT4lCiAgbmFfaWYoIi0tIikgJT4lCiAgbmFfaWYoIiIpICU+JQogIG5hX2lmKCIqIikKICBUQUJMRSA8LSBUQUJMRSAlPiUKICAgIGFzX3RpYmJsZSgpICU+JQogICAgcmVuYW1lKHt7bmV3X2NvbH19IDo9IHt7b2xkX2NvbH19KQogIHBhcnRBIDwtIFRBQkxFICU+JQogICAgc2VsZWN0KHt7bmV3X2NvbH19KQogIHBhcnRCIDwtIFRBQkxFICU+JQogICAgc2VsZWN0KC17e25ld19jb2x9fSkKICBwYXJ0QSA8LSBwYXJ0QSAlPiUKICBtdXRhdGUoe3tuZXdfY29sfX0gOj0gcGFydEEgJT4lCiAgICAgICAgICAgc2VsZWN0KHt7bmV3X2NvbH19KSAlPiUKICAgICAgICAgICBkcGx5cjo6cHVsbCh7e25ld19jb2x9fSkgJT4lCiAgICAgICAgICAgZ3N1YigiW1s6ZGlnaXQ6XV0rfFtcclxuXXxbWzpwdW5jdDpdXXwoW1s6Ymxhbms6XV0pXFwxKyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIiLCAuKSkKICBwYXJ0QiA8LSBwYXJ0QiAlPiUKICAgIG11dGF0ZShhY3Jvc3MoLmNvbHMgPSBldmVyeXRoaW5nKCksCiAgICAgICAgICAgICAgICBzdHJfcmVtb3ZlX2FsbCwgImEiKSkgJT4lCiAgICBtdXRhdGUoYWNyb3NzKC5jb2xzID0gZXZlcnl0aGluZygpLAogICAgICAgICAgICAgICAgc3RyX3JlbW92ZV9hbGwsICIsIikpCiAgcm0oVEFCTEUpCiAgVEFCTEUgPC0gYmluZF9jb2xzKHBhcnRBLAogICAgICAgICAgICAgICAgICAgICBwYXJ0QikKICBUQUJMRSA8LSBUQUJMRSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGNvbnRhaW5zKCIyMCIpLCBuYW1lc190byA9ICJZZWFyIiwgdmFsdWVzX3RvID0gcGl2b3RfY29sKQogIFRBQkxFCn0KYGBgCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqSSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nIGxpbmUgdG8gaGVscCBzZXBhcmF0ZSB0aGUgdGFibGVzLioqCgo8L2Rpdj4KCioqKgoKKipUYWJsZTExLjFhKioKCldlIHRoZW4gYXBwbHkgdGhpcyBmdW5jdGlvbiB0byB0aGUgdGFibGUsIHJpZGRpbmcgdGhlIHRhYmxlIG9mIGhlYWRpbmdzIGFuZCBlbnN1cmluZyBzb21lIG9mIG91ciBjb21tb25zIGFyZSBjb3JyZWN0bHkgb2YgbnVtZXJpYyBjbGFzcy4KCmBgYHtyfQpkaW0odGFibGUxMS4xYikKCnRhYmxlMTEuMWIgPC0gZGF0YV9wcmVwX3NldHRpbmdzKFRBQkxFID0gdGFibGUxMS4xYiwKICAgICAgICAgIG9sZF9jb2wgPSAiU2V0dGluZyBXaGVyZSBNZW50YWwgSGVhbHRoIFNlcnZpY2VXYXMgUmVjZWl2ZWQiLAogICAgICAgICAgbmV3X2NvbCA9ICJNSFNfc2V0dGluZyIsCiAgICAgICAgICBwaXZvdF9jb2wgPSAiUGVyY2VudCIpCgp0YWJsZTExLjFiIDwtIHRhYmxlMTEuMWIgJT4lCiAgZmlsdGVyKE1IU19zZXR0aW5nICE9ICJHZW5lcmFsIE1lZGljaW5lIikgJT4lCiAgZmlsdGVyKE1IU19zZXR0aW5nICE9ICJKdXZlbmlsZSBKdXN0aWNlIikgI0xlYWRpbmcgbGluZXMgd2l0aCBubyBkYXRhCgp0YWJsZTExLjFiIDwtIHRhYmxlMTEuMWIgJT4lCiAgbXV0YXRlKGFjcm9zcyhjKFllYXIsIFBlcmNlbnQpLCBhcy5udW1lcmljKSkKYGBgCgpXZSB3cml0ZSBhIGZ1bmN0aW9uIHRvIHNpbXBsaWZ5IHRoaXMgcHJvY2VzcyBmb3IgZGF0YSB0aGF0IHVzZXMgZGVtb2dyYXBoaWMgZ3JvdXBzIGFzIHVuaXRzIG9mIG9ic2VydmF0aW9uLgoKVGhlIGZ1bmN0aW9uIG5lZWRzIHRvOgoKLSByZW1vdmUgdGhlIGxhc3Qgcm93IG9mIHRoZSB0YWJsZQotIGdldCByaWQgb2YgY2VydGFpbiBwYXR0ZXJucwotIHRyYW5zaXRpb24gdGhlIGRhdGEgdG8gbG9uZyBmb3JtYXQKCmBgYHtyfQpkYXRhX3ByZXBfZGVtIDwtIGZ1bmN0aW9uKFRBQkxFLCBvbGRfY29sLCBuZXdfY29sLCBwaXZvdF9jb2wpewogIFRBQkxFIDwtIFRBQkxFWy1kaW0oVEFCTEUpWzFdLF0KICBUQUJMRSA8LSBUQUJMRSAlPiUKICBuYV9pZigibmMiKSAlPiUKICBuYV9pZigiLS0iKSAlPiUKICBuYV9pZigiIikgJT4lCiAgbmFfaWYoIioiKQogIFRBQkxFIDwtIFRBQkxFICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICByZW5hbWUoe3tuZXdfY29sfX0gOj0ge3tvbGRfY29sfX0pCiAgcGFydEEgPC0gVEFCTEUgJT4lCiAgICBkcGx5cjo6c2VsZWN0KHt7bmV3X2NvbH19KQogIHBhcnRCIDwtIFRBQkxFICU+JQogICAgZHBseXI6OnNlbGVjdCgte3tuZXdfY29sfX0pCiAgcGFydEEgPC0gcGFydEEgJT4lCiAgbXV0YXRlKHt7bmV3X2NvbH19IDo9IHBhcnRBICU+JQogICAgICAgICAgIGRwbHlyOjpzZWxlY3Qoe3tuZXdfY29sfX0pICU+JQogICAgICAgICAgIHB1bGwoe3tuZXdfY29sfX0pICU+JQogICAgICAgICAgIGdzdWIoIltcclxuXXxbWzpwdW5jdDpdXXwoW1s6Ymxhbms6XV0pXFwxKyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIiLCAuKSkKICBwYXJ0QSA8LSBwYXJ0QSAlPiUKICBtdXRhdGUoe3tuZXdfY29sfX0gOj0gZHBseXI6OmNhc2Vfd2hlbihzdHJpbmdyOjpzdHJfZGV0ZWN0KCEhYmFzZTo6YXMubmFtZShuZXdfY29sKSwgcGF0dGVybiA9ICIxIikgfiBiYXNlOjpwYXN0ZSgiQWdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfc3ViKCEhYmFzZTo6YXMubmFtZShuZXdfY29sKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9MiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5ncjo6c3RyX3N1YighIWJhc2U6OmFzLm5hbWUobmV3X2NvbCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydCA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSA0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXA9Il8iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICEhYmFzZTo6YXMubmFtZShuZXdfY29sKSkpCiAgcGFydEIgPC0gcGFydEIgJT4lCiAgICBtdXRhdGUoYWNyb3NzKC5jb2xzID0gZXZlcnl0aGluZygpLAogICAgICAgICAgICAgICAgc3RyX3JlbW92ZV9hbGwsICJhIikpICU+JQogICAgbXV0YXRlKGFjcm9zcyguY29scyA9IGV2ZXJ5dGhpbmcoKSwKICAgICAgICAgICAgICAgIHN0cl9yZW1vdmVfYWxsLCAiLCIpKQogIHJtKFRBQkxFKQogIFRBQkxFIDwtIGJpbmRfY29scyhwYXJ0QSwKICAgICAgICAgICAgICAgICAgICAgcGFydEIpCiAgVEFCTEUgPC0gVEFCTEUgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjb250YWlucygiMjAiKSwgbmFtZXNfdG8gPSAiWWVhciIsIHZhbHVlc190byA9IHBpdm90X2NvbCkKICBUQUJMRQp9CmBgYAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKkkgaW5jbHVkZWQgdGhlIGZvbGxvd2luZyBsaW5lIHRvIGhlbHAgc2VwYXJhdGUgdGhlIHRhYmxlcy4qKgoKPC9kaXY+CgoqKioKCioqVGFibGUxMS4yYSoqCgpXZSB1c2UgdGhlIHByb2R1Y2VkIGZ1bmN0aW9uIHRvIHdyYW5nbGUgdGhlIG5leHQgcGFpciBvZiB0YWJsZXMuIAoKYGBge3J9CmRpbSh0YWJsZTExLjJhKQoKdGFibGUxMS4yYSA8LSBkYXRhX3ByZXBfZGVtKFRBQkxFID0gdGFibGUxMS4yYSwKICAgICAgICAgIG9sZF9jb2wgPSAiRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWMiLAogICAgICAgICAgbmV3X2NvbCA9ICJEZW1vZ3JhcGhpYyIsCiAgICAgICAgcGl2b3RfY29sID0gIk51bWJlciIpCgp0YWJsZTExLjJhICU+JQogIGZpbHRlcighY29tcGxldGUuY2FzZXMoLikpICU+JQogIGRwbHlyOjpncm91cF9ieShEZW1vZ3JhcGhpYykgJT4lCiAgdGFsbHkoKQoKdGFibGUxMS4yYSA8LSB0YWJsZTExLjJhICU+JQogIGZpbHRlcihzdGF0czo6Y29tcGxldGUuY2FzZXMoLikgfCBEZW1vZ3JhcGhpYyA9PSAiQUlBTiIpCgp0YWJsZTExLjJhIDwtIHRhYmxlMTEuMmEgJT4lCiAgbXV0YXRlKGFjcm9zcyhjKFllYXIsIE51bWJlciksIGFzLm51bWVyaWMpKQpgYGAKCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipJIGluY2x1ZGVkIHRoZSBmb2xsb3dpbmcgbGluZSB0byBoZWxwIHNlcGFyYXRlIHRoZSB0YWJsZXMuKioKCjwvZGl2PgoKKioqCgoqKlRhYmxlMTEuMmIqKgoKYGBge3J9CmRpbSh0YWJsZTExLjJiKQoKdGFibGUxMS4yYiA8LSBkYXRhX3ByZXBfZGVtKFRBQkxFID0gdGFibGUxMS4yYiwKICAgICAgICAgIG9sZF9jb2wgPSAiRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWMiLAogICAgICAgICAgbmV3X2NvbCA9ICJEZW1vZ3JhcGhpYyIsCiAgICAgICAgICBwaXZvdF9jb2wgPSAiUGVyY2VudCIpCgp0YWJsZTExLjJiICU+JQogIGZpbHRlcighY29tcGxldGUuY2FzZXMoLikpICU+JQogIGdyb3VwX2J5KERlbW9ncmFwaGljKSAlPiUKICB0YWxseSgpCgp0YWJsZTExLjJiIDwtIHRhYmxlMTEuMmIgJT4lCiAgZmlsdGVyKGNvbXBsZXRlLmNhc2VzKC4pIHwgRGVtb2dyYXBoaWMgPT0gIkFJQU4iKQoKdGFibGUxMS4yYiA8LSB0YWJsZTExLjJiICU+JQogIG11dGF0ZShhY3Jvc3MoYyhZZWFyLCBQZXJjZW50KSwgYXMubnVtZXJpYykpCmBgYAoKV2UgcmVwZWF0IHRoaXMgcHJvY2VzcyBmb3IgdGhlIHJlbWFpbmluZyB0YWJsZXMuCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqSSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nIGxpbmUgdG8gaGVscCBzZXBhcmF0ZSB0aGUgdGFibGVzLioqCgo8L2Rpdj4KCioqKgoKKipUYWJsZSAxMS4zYSoqCgpgYGB7cn0KZGltKHRhYmxlMTEuM2EpCgp0YWJsZTExLjNhIDwtIGRhdGFfcHJlcF9kZW0oVEFCTEUgPSB0YWJsZTExLjNhLAogICAgICAgICAgb2xkX2NvbCA9ICJEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpYyIsCiAgICAgICAgICBuZXdfY29sID0gIkRlbW9ncmFwaGljIiwKICAgICAgICAgIHBpdm90X2NvbCA9ICJOdW1iZXIiKQoKdGFibGUxMS4zYSAlPiUKICBmaWx0ZXIoIWNvbXBsZXRlLmNhc2VzKC4pKSAlPiUKICBncm91cF9ieShEZW1vZ3JhcGhpYykgJT4lCiAgdGFsbHkoKQoKdGFibGUxMS4zYSA8LSB0YWJsZTExLjNhICU+JQogIGZpbHRlcihjb21wbGV0ZS5jYXNlcyguKSB8IERlbW9ncmFwaGljID09ICJBSUFOIikKCnRhYmxlMTEuM2EgPC0gdGFibGUxMS4zYSAlPiUKICBtdXRhdGUoYWNyb3NzKGMoWWVhciwgTnVtYmVyKSwgYXMubnVtZXJpYykpCmBgYAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKkkgaW5jbHVkZWQgdGhlIGZvbGxvd2luZyBsaW5lIHRvIGhlbHAgc2VwYXJhdGUgdGhlIHRhYmxlcy4qKgoKPC9kaXY+CgoqKioKCioqVGFibGUgMTEuM2IqKgoKYGBge3J9CmRpbSh0YWJsZTExLjNiKQoKdGFibGUxMS4zYiA8LSBkYXRhX3ByZXBfZGVtKFRBQkxFID0gdGFibGUxMS4zYiwKICAgICAgICAgIG9sZF9jb2wgPSAiRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWMiLAogICAgICAgICAgbmV3X2NvbCA9ICJEZW1vZ3JhcGhpYyIsCiAgICAgICAgICBwaXZvdF9jb2wgPSAiUGVyY2VudCIpCgp0YWJsZTExLjNiICU+JQogIGZpbHRlcighY29tcGxldGUuY2FzZXMoLikpICU+JQogIGdyb3VwX2J5KERlbW9ncmFwaGljKSAlPiUKICB0YWxseSgpCgp0YWJsZTExLjNiIDwtIHRhYmxlMTEuM2IgJT4lCiAgZmlsdGVyKGNvbXBsZXRlLmNhc2VzKC4pIHwgRGVtb2dyYXBoaWMgPT0gIkFJQU4iKQoKdGFibGUxMS4zYiA8LSB0YWJsZTExLjNiICU+JQogIG11dGF0ZShhY3Jvc3MoYyhZZWFyLCBQZXJjZW50KSwgYXMubnVtZXJpYykpCmBgYAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKkkgaW5jbHVkZWQgdGhlIGZvbGxvd2luZyBsaW5lIHRvIGhlbHAgc2VwYXJhdGUgdGhlIHRhYmxlcy4qKgoKPC9kaXY+CgoqKioKCioqVGFibGUgMTEuNGEqKgoKYGBge3J9CmRpbSh0YWJsZTExLjRhKQoKdGFibGUxMS40YSA8LSBkYXRhX3ByZXBfZGVtKFRBQkxFID0gdGFibGUxMS40YSwKICAgICAgICAgIG9sZF9jb2wgPSAiRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWMiLAogICAgICAgICAgbmV3X2NvbCA9ICJEZW1vZ3JhcGhpYyIsCiAgICAgICAgICBwaXZvdF9jb2wgPSAiTnVtYmVyIikKCnRhYmxlMTEuNGEgJT4lCiAgZmlsdGVyKCFjb21wbGV0ZS5jYXNlcyguKSkgJT4lCiAgZ3JvdXBfYnkoRGVtb2dyYXBoaWMpICU+JQogIHRhbGx5KCkKCnRhYmxlMTEuNGEgPC0gdGFibGUxMS40YSAlPiUKICBmaWx0ZXIoY29tcGxldGUuY2FzZXMoLikgfCBEZW1vZ3JhcGhpYyA9PSAiQUlBTiIpCgp0YWJsZTExLjRhIDwtIHRhYmxlMTEuNGEgJT4lCiAgbXV0YXRlKGFjcm9zcyhjKFllYXIsIE51bWJlciksIGFzLm51bWVyaWMpKQpgYGAKCjxzdHlsZT4KZGl2LnJlZCB7IGJhY2tncm91bmQtY29sb3I6I0ZGRTZFNjsgYm9yZGVyLXJhZGl1czogNXB4OyBwYWRkaW5nOiAyMHB4O30KPC9zdHlsZT4KPGRpdiBjbGFzcyA9ICJyZWQiPgoKKipJIGluY2x1ZGVkIHRoZSBmb2xsb3dpbmcgbGluZSB0byBoZWxwIHNlcGFyYXRlIHRoZSB0YWJsZXMuKioKCjwvZGl2PgoKKioqCgoqKlRhYmxlIDExLjRiKioKCmBgYHtyfQpkaW0odGFibGUxMS40YikKCnRhYmxlMTEuNGIgPC0gZGF0YV9wcmVwX2RlbShUQUJMRSA9IHRhYmxlMTEuNGIsCiAgICAgICAgICBvbGRfY29sID0gIkRlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljIiwKICAgICAgICAgIG5ld19jb2wgPSAiRGVtb2dyYXBoaWMiLAogICAgICAgICAgcGl2b3RfY29sID0gIlBlcmNlbnQiKQoKdGFibGUxMS40YiAlPiUKICBmaWx0ZXIoIWNvbXBsZXRlLmNhc2VzKC4pKSAlPiUKICBncm91cF9ieShEZW1vZ3JhcGhpYykgJT4lCiAgdGFsbHkoKQoKdGFibGUxMS40YiA8LSB0YWJsZTExLjRiICU+JQogIGZpbHRlcihjb21wbGV0ZS5jYXNlcyguKSB8IERlbW9ncmFwaGljID09ICJBSUFOIikKCnRhYmxlMTEuNGIgPC0gdGFibGUxMS40YiAlPiUKICBtdXRhdGUoYWNyb3NzKGMoWWVhciwgUGVyY2VudCksIGFzLm51bWVyaWMpKQpgYGAKCk5vdyB0aGF0IHdlJ3ZlIHdyYW5nbGVkIHRoZSBkYXRhLCB3ZSBjYW4gZ28gYWhlYWQgYW5kIHByb2NlZWQgd2l0aCBvdXIgYW5hbHlzaXMuIAoKIyMgKipEYXRhIEFuYWx5c2lzKioKKioqIAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKkluIHRoaXMgc2VjdGlvbiwgd2Ugb25seSBhbmFseXplZCBkYXRhIGZyb20gdGFibGVzIDItNC4gRGF0YSBmcm9tIHRhYmxlIDEgaXMgdmVyeSBkaWZmZXJlbnQgdGhhbiBkYXRhIGZyb20gdGFibGVzIDItNC4gRm9yIGV4cGVkaWVuY3ksIEkgZGlkIG5vdCBpbmNsdWRlIGFuIGV4YW1wbGUgd2l0aCBkYXRhIGZyb21lIHRhYmxlIDEuIFRoZSBmb2xsb3dpbmcgY29kZSwgaG93ZXZlciwgY2FuIGVhc2lseSBiZSByZXB1cnBvc2VkIHRvIGFjY29tcGxpc2ggdGhhdCBvbmNlIGEgc3BlY2lmaWMgZ3JvdXAgaGFzIGJlZW4gaWRlbnRpZmllZCB0byBjb25kdWN0IHRoZSB0ZXN0IG9uLioqCgo8L2Rpdj4KCldlIHdvdWxkIGxpa2UgdG8gY29uZHVjdCBhIFtjaGktc3F1YXJlZCB0ZXN0XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DaGktc3F1YXJlZF90ZXN0P29sZGZvcm1hdD10cnVlKSBmb3IgaW5kZXBlbmRlbmNlLiAKClRvIGNvbmR1Y3QgdGhpcyBzdGF0aXN0aWNhbCB0ZXN0LCB3ZSBuZWVkIHRvIHByb2R1Y2UgYSAyeDIgdGFibGUuCgpUaGUgZm9sbG93aW5nIGNvZGUgc3Vic2V0cyB0aGUgZGF0YSB3ZSBuZWVkIGFuZCBtYWtlcyB0aGUgbmVjZXNzYXJ5IG1hbmlwdWxhdGlvbnMgc28gdGhhdCB0aGUgdW5pdHMgb2Ygb2JzZXJ2YXRpb24gYXJlIGFwcHJvcHJpYXRlLiAKCmBgYHtyfQpjaGlfc3F1YXJlXzExLjJhIDwtIHRhYmxlMTEuMmEgJT4lCiAgZmlsdGVyKFllYXIgJWluJSBjKDIwMDksIDIwMTgpKSAlPiUKICBmaWx0ZXIoRGVtb2dyYXBoaWMgJWluJSBjKCJNYWxlIiwiRmVtYWxlIikpICU+JQogIG11dGF0ZShOdW1iZXIgPSBOdW1iZXIgKiAxMDAwKQpgYGAKClRoZSByZXN1bHRpbmcgb2JqZWN0IGlzIHN0aWxsIGluIGxvbmcgZm9ybWF0LgoKYGBge3J9CmNoaV9zcXVhcmVfMTEuMmEKYGBgCgpUbyBjb25kdWN0IGEgY2hpLXNxdWFyZWQgdGVzdCBmb3IgaW5kZXBlbmNlIHdlIHdpbGwgbmVlZCBhIFtjb250aW5nZW5jeSB0YWJsZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29udGluZ2VuY3lfdGFibGU/b2xkZm9ybWF0PXRydWUpLiAKCkEgY29udGluZ2VuY3kgdGFibGUgY2FuIGJlIHByb2R1Y2VkIGZyb20gZGF0YSBpbiBsb25nIGZvcm1hdCBieSB0cmFuc2Zvcm1pbmcgdGhlIGRhdGEgdG8gd2lkZSBmb3JtYXQgYW5kIHJlcHVycG9zaW5nIHNvbWUgdmFsdWVzIGFzIHJvdyBuYW1lcy4gCgpgYGB7cn0KY2hpX3NxdWFyZV8xMS4yYSA8LSBjaGlfc3F1YXJlXzExLjJhICU+JQogIHRpZHlyOjpwaXZvdF93aWRlcihuYW1lc19mcm9tID0gWWVhciwKICAgICAgICAgICAgICBuYW1lc19wcmVmaXggPSAiWWVhciIsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gTnVtYmVyKSAlPiUKICB0aWJibGU6OmNvbHVtbl90b19yb3duYW1lcygiRGVtb2dyYXBoaWMiKQpgYGAKClRoZSBmaW5hbCBvYmplY3Qgc2hvdWxkIGxvb2sgbGlrZSB0aGlzLiAKCmBgYHtyfQpjaGlfc3F1YXJlXzExLjJhCmBgYAoKVGhlIGNoaS1zcXVhcmVkIHRlc3QgZm9yIGluZGVwZW5kZW5jZSBjYW4gYmUgY29uZHVjdGVkIHVzaW5nIHRoZSBgc3RhdHM6OmNoaXNxLnRlc3QoKWAgZnVuY3Rpb24uIAoKYGBge3J9CnN0YXRzOjpjaGlzcS50ZXN0KGNoaV9zcXVhcmVfMTEuMmEpCmBgYAoKV2UgY2FuIHJlcGVhdCB0aGlzIHByb2Nlc3MgZm9yIHRoZSByZW1haW5pbmcgdGFibGVzLgoKYGBge3J9CmNoaV9zcXVhcmVfMTEuM2EgPC0gdGFibGUxMS4zYSAlPiUKICBmaWx0ZXIoWWVhciAlaW4lIGMoMjAwOSwgMjAxOCkpICU+JQogIGZpbHRlcihEZW1vZ3JhcGhpYyAlaW4lIGMoIk1hbGUiLCJGZW1hbGUiKSkgJT4lCiAgbXV0YXRlKE51bWJlciA9IE51bWJlciAqIDEwMDApCgpjaGlfc3F1YXJlXzExLjNhIDwtIGNoaV9zcXVhcmVfMTEuM2EgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IFllYXIsCiAgICAgICAgICAgICAgbmFtZXNfcHJlZml4ID0gIlllYXIiLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IE51bWJlcikgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCJEZW1vZ3JhcGhpYyIpCgpjaGlfc3F1YXJlXzExLjNhCmBgYAoKYGBge3J9CmNoaXNxLnRlc3QoY2hpX3NxdWFyZV8xMS4zYSkKYGBgCgpgYGB7cn0KY2hpX3NxdWFyZV8xMS40YSA8LSB0YWJsZTExLjRhICU+JQogIGZpbHRlcihZZWFyICVpbiUgYygyMDA5LCAyMDE4KSkgJT4lCiAgZmlsdGVyKERlbW9ncmFwaGljICVpbiUgYygiTWFsZSIsIkZlbWFsZSIpKSAlPiUKICBtdXRhdGUoTnVtYmVyID0gTnVtYmVyICogMTAwMCkKCmNoaV9zcXVhcmVfMTEuNGEgPC0gY2hpX3NxdWFyZV8xMS40YSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gWWVhciwKICAgICAgICAgICAgICBuYW1lc19wcmVmaXggPSAiWWVhciIsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gTnVtYmVyKSAlPiUKICBjb2x1bW5fdG9fcm93bmFtZXMoIkRlbW9ncmFwaGljIikKCmNoaV9zcXVhcmVfMTEuNGEKYGBgCgpgYGB7cn0KY2hpc3EudGVzdChjaGlfc3F1YXJlXzExLjRhKQpgYGAKCiMjICoqRGF0YSBWaXN1YWxpemF0aW9uKioKKioqIAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKlRoaXMgaXMgdGhlIGludGVudGlvbmFsbHkgdGVycmlibGUgcGxvdCB0aGF0IHJlcXVpcmVzIGZhY2V0aW5nLioqCgo8L2Rpdj4KCmBgYHtyfQp0YWJsZTExLjFiICU+JQogIGdncGxvdDI6OmdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBQZXJjZW50LCBncm91cCA9IE1IU19zZXR0aW5nKSkgKwogIGdncGxvdDI6Omdlb21fbGluZSgpICsKICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDksIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwOSwgMjAxOCkpICsKICBnZ3Bsb3QyOjpsYWJzKHRpdGxlID0gIlNldHRpbmdzIFdoZXJlIE1lbnRhbCBIZWFsdGggU2VydmljZXMgV2VyZSBSZWNlaXZlZCBpbiBQYXN0IFllYXJcbmFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJQZXJjZW50YWdlcywgMjAwMi0yMDE4IikKYGBgCgo8c3R5bGU+CmRpdi5yZWQgeyBiYWNrZ3JvdW5kLWNvbG9yOiNGRkU2RTY7IGJvcmRlci1yYWRpdXM6IDVweDsgcGFkZGluZzogMjBweDt9Cjwvc3R5bGU+CjxkaXYgY2xhc3MgPSAicmVkIj4KCioqVGhlIHBsb3RzIGJlbG93IG5lZWQgdG8gYmUgY29ycmVjdGx5IGZhY2V0ZWQuIEtlZXAgaW4gbWluZCB0aGF0IHRhYmxlcyAxMS4yKyBtdXN0IGJlIGZhY2V0ZWQgYnkgZGVtb2dyYXBoaWMgZ3JvdXAgdHlwZSBhbmQgbm90IGJ5IHNldHRpbmcgdHlwZS4qKgoKPC9kaXY+CgpgYGB7cn0KdGFibGUxMS4xYiAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gUGVyY2VudCwgZ3JvdXAgPSBNSFNfc2V0dGluZykpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA5LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDksIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDksIDIwMTgpKSArCiAgbGFicyh0aXRsZSA9ICJTZXR0aW5ncyBXaGVyZSBNZW50YWwgSGVhbHRoIFNlcnZpY2VzIFdlcmUgUmVjZWl2ZWQgaW4gUGFzdCBZZWFyXG5hbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTciLAogICAgICAgc3VidGl0bGUgPSAiUGVyY2VudGFnZXMsIDIwMDItMjAxOCIpCmBgYAoKYGBge3J9CnRhYmxlMTEuMmIgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IFBlcmNlbnQsIGdyb3VwID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA5LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA5LCAyMDE4KSkgKwogIGxhYnModGl0bGUgPSAiTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljcywgUGVyY2VudGFnZXMsIDIwMDQtMjAxOCIpCmBgYAoKYGBge3J9CnRhYmxlMTEuM2IgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IFBlcmNlbnQsIGdyb3VwID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA5LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA5LCAyMDE4KSkgKwogIGxhYnModGl0bGUgPSAiTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIHdpdGggU2V2ZXJlIEltcGFpcm1lbnQgaW4gUGFzdCBZZWFyXG5hbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTciLAogICAgICAgc3VidGl0bGUgPSAiQnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNi0yMDE4IikKYGBgCgpgYGB7cn0KdGFibGUxMS40YiAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gUGVyY2VudCwgZ3JvdXAgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA5LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDksIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDksIDIwMTgpKSArIAogIGxhYnModGl0bGUgPSAiUmVjZWlwdCBvZiBUcmVhdG1lbnQgZm9yIERlcHJlc3Npb24gaW4gUGFzdCBZZWFyIGFtb25nXG5QZXJzb25zIEFnZWQgMTIgdG8gMTcgd2l0aCBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyIiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDQtMjAxOCIpCmBgYAoKPHN0eWxlPgpkaXYucmVkIHsgYmFja2dyb3VuZC1jb2xvcjojRkZFNkU2OyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gInJlZCI+CgoqKlRoZSBwbG90cyBjcmVhdGVkIChhZnRlciBmYWNldGluZyBwcm9wZXJseSkgY2FuIGJlIHVzZWQgdG8gYW5zd2VyIHRoZSBxdWVzdGlvbnMgbGlzdGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGNhc2Ugc3R1ZHkuIEFmdGVyIGZpbmFsaXppbmcgdGhlIHBsb3RzLCBzb21lIHRpbWUgc2hvdWxkIGJlIHNwZW50IHRvd2FyZHMgZnJhbWluZyB0aGUgdmlzdWFsaXphdGlvbnMgaW4gc3VjaCBhIHdheSB0byB1bmRlcnNjb3JlIGhvdyB0aGV5IHdlcmUgdXNlZCB0byBhc253ZXIgdGhlIHF1ZXN0aW9uLioqCgo8L2Rpdj4KCiMjICoqU3VtbWFyeSoqCioqKiAKCiMjICoqU3VnZ2VzdGVkIEhvbWV3b3JrKioKKioqIAoKIyMgKipBZGRpdGlvbmFsIEluZm9ybWF0aW9uKioKKioqCgojIyMgSGVscGZ1bCBMaW5rcwoKCioqVGhpcyBuZWVkcyB0byBiZSB1cGRhdGVkKioKCltndWlkZV0oaHR0cHM6Ly9icmlhdHRlLmdpdGh1Yi5pby9nZ2NvcnIvKSBmb3IgdXNpbmcgR0dhbGx5IHRvIGNyZWF0ZSBjb3JyZWxhdGlvbiBwbG90cwoKPHU+VGVybXMgYW5kIGNvbmNlcHRzIGNvdmVyZWQ6PC91PiAgCgpbVGlkeXZlcnNlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltSU3R1ZGlvIGNoZWF0c2hlZXRzXShodHRwczovL3JzdHVkaW8uY29tL3Jlc291cmNlcy9jaGVhdHNoZWV0cy8pe3RhcmdldD0iX2JsYW5rIn0gIAoKPHU+UGFja2FnZXMgdXNlZCBpbiB0aGlzIGNhc2Ugc3R1ZHk6IDwvdT4KCiBQYWNrYWdlICAgfCBVc2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSl7dGFyZ2V0PSJfYmxhbmsifSAgICAgICB8IHRvIGVhc2lseSBsb2FkIGFuZCBzYXZlIGRhdGEgClt0aWR5dmVyc2VdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCBSIHBhY2thZ2VzIGZvciBkYXRhIHNjaWVuY2UKW3J2ZXN0XShodHRwczovL2dpdGh1Yi5jb20vdGlkeXZlcnNlL3J2ZXN0KXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzY3JhcGUgd2ViIHBhZ2VzCgoKIyMjIEFja25vd2xlZGdlbWVudHMKCldlIHdvdWxkIGxpa2UgdG8gYWNrbm93bGVkZ2UgW1RhbWFyIE1lbmRlbHNvbl0oaHR0cHM6Ly93d3cuamhzcGguZWR1L2ZhY3VsdHkvZGlyZWN0b3J5L3Byb2ZpbGUvMTc3MC90YW1hci1tZW5kZWxzb24pIGZvciBhc3Npc3RpbmcgaW4gZnJhbWluZyB0aGUgbWFqb3IgZGlyZWN0aW9uIG9mIHRoZSBjYXNlIHN0dWR5LgoKV2Ugd291bGQgYWxzbyBsaWtlIHRvIGFja25vd2xlZGdlIHRoZSBbQmxvb21iZXJnIEFtZXJpY2FuIEhlYWx0aCBJbml0aWF0aXZlXShodHRwczovL2FtZXJpY2FuaGVhbHRoLmpodS5lZHUvKSBmb3IgZnVuZGluZyB0aGlzIHdvcmsuIAoKCiMjIyAqKlJBIE5vdGVzKioKCltUaGlzIGlzIHRoZSBtb3RpdmF0aW5nIGFydGljbGUgZm9yIHRoaXMgY2FzZSBzdHVkeV0oaHR0cHM6Ly9wdWJtZWQubmNiaS5ubG0ubmloLmdvdi8zMDg2OTkyNy8pLiBJbiB0aGlzIGFydGljbGUsIHRoZXkgd2ViIHNjcmFwZSB0byBvYnRhaW4gdGhlIGRhdGEgdGhleSBuZWVkLiAKCltIZXJlIGlzIHRoZSBMaWViZXIgSW5zdGl0dXRlJ3MgcmVzb3VyY2Ugb24gd2ViIHNjcmFwZV0oaHR0cDovL3Jlc2VhcmNoLmxpYmQub3JnL3JzdGF0c2NsdWIvcG9zdC9pbnRyb2R1Y3Rpb24tdG8tc2NyYXBpbmctYW5kLXdyYW5naW5nLXRhYmxlcy1mcm9tLXJlc2VhcmNoLWFydGljbGVzLyMuWHc4NzhaTktoUUopCgpbSGVyZSBpcyBhIHJlc291Y2UgdGhlIExpZWJlciBJbnN0aXR1dGUgc291cmNlIGFib3ZlIHJlZmVyc2UgdG9dKGh0dHA6Ly9ibG9nLmNvcnluaXNzZW4uY29tLzIwMTUvMDEvdXNpbmctcnZlc3QtdG8tc2NyYXBlLWh0bWwtdGFibGUuaHRtbCkKCltIZXJlIGFzIGEgZ29vZCByZXNvdXJjZSB0byBsZWFybiBob3cgdG8gd2ViIHNjcmFwZV0oaHR0cHM6Ly9yc3R1ZGlvLXB1YnMtc3RhdGljLnMzLmFtYXpvbmF3cy5jb20vMjY2NDMwX2YzZmQ0NjYwYjI3NDQ3NTFhYjE0NGFhMTMwNzY4YTA2Lmh0bWwpCgpbVGhpcyBpcyB0aGUgc2V0IG9mIHRhYmxlcyB3ZSB3b3VsZCBsaWtlIHRvIGNvbnNpZGVyXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pCg==